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&lt;Model&gt;改为List&lt;Model&gt;时请检查是否有效。 你能把这个作为答案吗,因为它按照你的建议工作:) 嗨,你解决过这个问题吗?我尝试使用 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 的字段

Spring Boot 休息忽略一类

使用spring-boot对rest服务进行访问控制

rest-spring-boot-starter

列出所有已部署的 REST 端点(spring-boot、tomcat)

初入spring boot(八 )Spring Data REST