Spring Boot 忽略 Rest Controller 中的 Jackson 注释
Posted
技术标签:
【中文标题】Spring Boot 忽略 Rest Controller 中的 Jackson 注释【英文标题】:Spring Boot ignoring Jackson Annotations in Rest Controller 【发布时间】:2018-07-07 11:12:19 【问题描述】:所以我有一个抽象根类Model
,它有各种子类。模型注释如下:
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "model")
@JsonSubTypes(
@JsonSubTypes.Type(value = LowerBoundThresholdModel.class, name = "LowerBoundThresholdAnomalyDetector"),
@JsonSubTypes.Type(value = UpperBoundThresholdModel.class, name = "UpperBoundThresholdAnomalyDetector"),
@JsonSubTypes.Type(value = MovingAverageLowerBoundThresholdModel.class, name = "MovingAverageLowerBoundThresholdAnomalyDetector"),
@JsonSubTypes.Type(value = MovingAverageUpperBoundThresholdModel.class, name = "MovingAverageUpperBoundThresholdAnomalyDetector"),
@JsonSubTypes.Type(value = WindowedUpperBoundThresholdModel.class, name = "WindowedLowerBoundThresholdAnomalyDetector"),
@JsonSubTypes.Type(value = WindowedUpperBoundThresholdModel.class, name = "WindowedUpperBoundThresholdAnomalyDetector")
)
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Data
public abstract class Model
我有一个用@RestController
注释的控制器和一个这样的方法:
@GetMapping("/api/v1/models")
public ResponseEntity<Iterable<Model>> getAllModels()
try
return ResponseEntity.ok(modelService.getAll());
catch (Exception e)
return ResponseEntity.status(500).build();
我有一个正确序列化模型的测试:
public class JacksonTest extends AbstractApplicationTest
@Autowired
ObjectMapper mapper;
@Test
public void shouldSerialiseEvent() throws JsonProcessingException
LowerBoundThresholdModel lowerBoundThresholdModel = new LowerBoundThresholdModel();
lowerBoundThresholdModel.setThreshold(1.0);
String s = mapper.writeValueAsString(lowerBoundThresholdModel);
assertThat(s).contains("model").contains("LowerBoundThresholdAnomalyDetector");
但是,当我测试实际的 RestController 时,它似乎没有使用 Jackson 注释,也没有按照配置在 model
字段中包含类信息:
@Test
public void shouldReturnListOfExistingModels() throws Exception
LowerBoundThresholdModel lowerBoundThresholdModel = new LowerBoundThresholdModel();
lowerBoundThresholdModel.setThreshold(1.0);
lowerBoundThresholdModelRepository.save(lowerBoundThresholdModel);
windowedLowerBoundThresholdModelRepository.save(windowedLowerBoundThresholdModel);
mockMvc.perform(get("/api/v1/models"))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$[0].model", is("LowerBoundThresholdModel")))
.andExpect(MockMvcResultMatchers.jsonPath("$[0].threshold", is(lowerBoundThresholdModel.getThreshold())))
但是这个测试失败了no such JSON path $[0].model
如何让控制器使用相同的对象映射器,以便控制器的 JSON 输出正确?
编辑:如果我删除andExpect(MockMvcResultMatchers.jsonPath("$[0].model", is("LowerBoundThresholdModel")))
行,它就会通过,所以它与Iterable
没有被转换为索引数组无关
【问题讨论】:
Iterable<Model>
改为List<Model>
时请检查是否有效。
你能把这个作为答案吗,因为它按照你的建议工作:)
嗨,你解决过这个问题吗?我尝试使用 ResponseEntity,但没有,但我无法让它工作
【参考方案1】:
Iterator
不允许对项目列表进行索引访问。它只返回下一个元素。所以调用$[0]
失败。
通过将接口扩大到List
,它可以按预期工作。
@GetMapping("/api/v1/models")
public ResponseEntity<List<Model>> getAllModels()
try
return ResponseEntity.ok(modelService.getAll());
catch (Exception e)
return ResponseEntity.status(500).build();
【讨论】:
好吧,有趣的是它仍然可以与Iterable
一起使用它只是不尊重杰克逊的注释。我仍然可以访问使用索引呈现的 JSON,即使它是 Iterable
,它只是未填充的 model
字段以上是关于Spring Boot 忽略 Rest Controller 中的 Jackson 注释的主要内容,如果未能解决你的问题,请参考以下文章
在 Spring Boot + Spring Data Rest 中反序列化时忽略带有 @JsonProperty 的字段