Jackson - la propriété @jsontypeinfo est mappée en tant que null?

Je fais face à ce problème. Disons que j'ai cette réponse:

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

Ensuite, en fonction de l'attributexercise_type je veux instancier différentes instances d'objets (sous-classes de ExerciseResponseDTO), donc je crée ce mélange dans:

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

Donc je crée mon ObjectMapper comme suit

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

Mon test:

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 

Le problème est que, pour une raison quelconque, le exercise_type attribut utilisé aussi bien sur @JsonTypeInfo est mappé comme null. Une idée de comment je peux résoudre ce problème?

27
demandé sur jscherman 2015-11-09 17:21:26

2 réponses

Enfin, j'ai trouvé la solution dans le document API

Remarque sur la visibilité de l'Identificateur de type: par défaut, désérialisation (utilisation lors de la lecture de JSON) de l'identifiant de type est complètement géré par Jackson, et n'est pas transmis aux désérialiseurs. Toutefois, si la désiré, il est possible de définir la propriété visible = true dans lequel la propriété case sera transmise telle quelle aux désérialiseurs (et définie via setter ou champ) sur désérialisation.

Donc la solution ajoutait simplement l'attribut' visible ' comme suit

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

J'espère que cela aide quelqu'un d'autre.

55
répondu jscherman 2016-11-22 16:48:51

Selon @ jscherman réponse en définissant, 'visible' true dans JsonTypeInfo aidera à accéder à exercise_type en tant que champ.

Si vous utilisez la même classe pour sérialiser également, le JSON résultant affichera exercise_type deux fois. Il est donc préférable de mettre à jour include vers JsonTypeInfo. As. EXISTING_PROPERTY

Et il vaut également la peine de regarder toutes les autres options pour inclure.

0
répondu Shashank 2018-10-04 06:28:23