Je fais face à ce problème. Disons que j'ai cette réponse:
{
"id":"decaa828741611e58bcffeff819cdc9f",
"statement":"question statement",
"exercise_type":"QUESTION"
}
Ensuite, basé sur type_exercice attribut, 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, l'attribut exerc_type utilisé comme propriété sur @JsonTypeInfo
est mappé comme null. Une idée comment je peux résoudre ce problème?
Enfin, j'ai trouvé la solution dans le API Doc
Remarque sur la visibilité de l'identifiant de type: par défaut, la désérialisation (à utiliser lors de la lecture de JSON) de l'identifiant de type est entièrement gérée par Jackson et n'est pas transmise aux désérialiseurs. Cependant, si vous le souhaitez, il est possible de définir la propriété visible = true, auquel cas la propriété sera transmise telle quelle aux désérialiseurs (et définie via setter ou field) lors de la désérialisation.
La solution consistait donc simplement à ajouter 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 ceci aide quelqu'un d'autre.
Selon @ réponse jscherman en définissant, 'visible' true dans JsonTypeInfo aidera à accéder à exerced_type en tant que champ.
Si vous utilisez également la même classe pour sérialiser, le JSON résultant affichera exercice_type deux fois. Il est donc préférable de mettre également à jour l'inclusion vers JsonTypeInfo.As.EXISTING_PROPERTY
Et cela vaut également la peine de regarder toutes les autres options pour inclure.