web-dev-qa-db-ja.com

ジャクソン-@JsonTypeInfoプロパティがnullとしてマップされていますか?

私はこの問題に対処しています。この応答があるとしましょう:

{  
    "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としてマップされていることです。どのように私はこれを解決できますか?

40
jscherman

最後に、 API Doc で解決策を見つけました

型識別子の可視性に関する注意:デフォルトでは、型識別子のデシリアライズ(JSONの読み取り中に使用)はJacksonによって完全に処理され、デシリアライザーには渡されません。ただし、必要に応じて、プロパティvisible = trueを定義することができます。この場合、プロパティは、デシリアライズ時にデシリアライザにそのまま渡されます(およびセッターまたはフィールドを介して設定されます)。

そのため、解決策は次のように「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  
{}  

これが他の誰かに役立つことを願っています。

77
jscherman

@ jscherman answer 設定により、JsonTypeInfoの 'visible' trueは、フィールドとしてExercise_typeにアクセスするのに役立ちます。

同じクラスを使用してシリアル化する場合、結果のJSONにはExercise_typeが2回表示されます。したがって、インクルードも JsonTypeInfo.As.EXISTING_PROPERTY に更新することをお勧めします

また、 他のすべてのオプション を含めることも検討する価値があります。

3
Shashank