杰克逊 - @JsonTypeInfo属性被映射为null?

时间:2015-11-09 14:21:26

标签: java jackson json-deserialization

我正在处理这个问题。让我们说我有这样的回应:

{  
    "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 

问题在于,出于某种原因,在@JsonTypeInfo上用作属性的 exercise_type 属性被映射为 null 。 知道如何解决这个问题吗?

2 个答案:

答案 0 :(得分:74)

最后,我在API Doc

中找到了解决方案
  

关于类型标识符可见性的注意事项:默认情况下,反序列化   (在读取JSON期间使用)类型标识符已完全处理   由杰克逊,并没有传递给反序列化者。但是,如果是这样   期望,可以在其中定义属性visible = true   case属性将按原样传递给反序列化器(并通过设置   反序列化的setter或字段。

因此,解决方案只是添加' 可见'属性如下

@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  
{}  

希望这有助于其他人。

答案 1 :(得分:3)

根据@jscherman answer的设置,JsonTypeInfo中的“ visible”为true将有助于以字段的形式访问exercise_type。

如果您也使用同一类进行序列化,则生成的JSON将具有exercise_type出现两次。因此最好也将include更新为JsonTypeInfo.As.EXISTING_PROPERTY

值得一看的是all other options的包含内容。