Jackson - @JsonTypeInfo属性被映射为null?

75

假设我有以下JSON:

{  
    "id":"decaa828741611e58bcffeff819cdc9f",
    "statement":"question statement",
    "exercise_type":"QUESTION"
}

然后,根据exercise_type字段,我想要实例化不同的对象实例(ExerciseResponseDTO的子类)。为了实现这一点,我尝试创建了这个混合体:

@JsonTypeInfo(  
    use = JsonTypeInfo.Id.NAME,  
    include = JsonTypeInfo.As.PROPERTY,  
    property = "exercise_type")  
@JsonSubTypes({  
    @Type(value = ExerciseChoiceResponseDTO.class, name = "CHOICE"),  
    @Type(value = ExerciseQuestionResponseDTO.class, name = "QUESTION")})  
public abstract class ExerciseMixIn  
{}  

public abstract class ExerciseResponseDTO {

    private String id;
    private String statement;
    @JsonProperty(value = "exercise_type") private String exerciseType;
    
    // Getters and setters 
}

public class ExerciseQuestionResponseDTO
    extends ExerciseResponseDTO {}

public class ExerciseChoiceResponseDTO
    extends ExerciseResponseDTO {}

然后将映射器ObjectMapper设置如下

ObjectMapper mapper = new ObjectMapper();
mapper.addMixIn(ExerciseResponseDTO.class, ExerciseMixIn.class);

但出于某些原因,这个测试失败了:

ExerciseResponseDTO exercise = mapper.readValue(serviceResponse, ExerciseResponseDTO.class)
Assert.assertTrue(exercise.getClass() == ExerciseQuestionResponseDTO.class);    // OK
Assert.assertEquals("decaa828741611e58bcffeff819cdc9f" exercise.getId());       // OK
Assert.assertEquals("question statement", exercise.getStatement());             // OK
Assert.assertEquals("QUESTION", exercise.getExerciseType());                    // FAIL. Expected: "QUESTION", actual: null

看起来存在一个问题,特别是与exercise_type属性的映射似乎出了一些问题,因为所有其他字段都映射得很好。您有什么想法是什么原因导致这种情况吗?

2个回答

178

最终,我在API文档中找到了解决方案。

关于类型标识符的可见性说明:默认情况下,在反序列化(读取JSON时)期间,类型标识符的反序列化完全由Jackson处理,并且不会传递给反序列化程序。但是,如果需要,可以定义属性visible=true,在这种情况下,属性将原样传递给反序列化程序(并通过setter或字段设置)进行反序列化。

因此,解决方案就是如下所示添加“visible”属性。

@JsonTypeInfo(  
    use = JsonTypeInfo.Id.NAME,  
    include = JsonTypeInfo.As.PROPERTY,  
    property = "exercise_type",
    visible = true)  
@JsonSubTypes({  
    @Type(value = ExerciseChoiceResponseDTO.class, name = "CHOICE"),  
    @Type(value = ExerciseQuestionResponseDTO.class, name = "QUESTION")})  
public abstract class ExerciseMixIn  
{}  

9
我希望上帝能够赏赐你并给予你所需要的一切:)))) 我为此搜索了几个小时。 - Alex
无法工作,这是由openapi-generator生成的默认实现,但在调用我的REST控制器时序列化为JSON时,我的字段始终为“null”。 - Saad Benbouzid
cool。同样适用于EXISTING_PROPERTY。 - Kampaii
调试了整个库,发现是“visible”属性引起的问题。简单的谷歌搜索把我带到了这里。 - Ayhan APAYDIN

8
根据@jscherman回答中的设置,在JsonTypeInfo中将“visible”设置为true将有助于访问exercise_type作为字段。
如果您还使用相同的类进行序列化,则生成的JSON将出现两次exercise_type。因此,最好也将include更新为JsonTypeInfo.As.EXISTING_PROPERTY
同时,值得查看所有其他选项以包含在内。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接