Deserializador personalizado de Jackson para um campo com tipos polimórficos
Atualizar:
Eu tentei depurar o código fonte de jackson e descobri que no método
deserialize(JsonParser jp, DeserializationContext ctxt)
do
SettableBeanProperty.java
quando o_valueTypeDeserializer
não for nulo, nunca usará_valueDeserializer
.
Essa é uma suposição correta de que TypeDeserializer deve ser mais adequado que ValueDeserializer?
Estou tentando usar@JsonDeserialize
definir desserializador personalizado para um campo com tipos polimórficos. Posso conseguir usar@JsonDeserialize
e@JsonTypeInfo
separadamente. Mas quando eu os uso juntos, parece que o@JsonDeserialize
anotação é ignorada.
Aqui está minha hierarquia de classes:
1. Definition.java@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type", defaultImpl = Definition.class)
@JsonSubTypes({@Type(value = Definition.class, name = "normal"),
@Type(value = FormDefinition.class, name = "form")})
public class Definition {
private String name;
private String description;
// getter&setter for name&description
}
2. FormDefinition.javapublic class FormDefinition extends Definition {
private String formName;
@JsonDeserialize(using = DefinitionDeserializer.class)
private Definition definition;
public String getFormName() {
return formName;
}
public void setFormName(String formName) {
this.formName = formName;
}
public void setDefinition(Definition definition) {
this.definition = definition;
}
}
3. DefinitionDeserializer.javapublic class DefinitionDeserializer extends JsonDeserializer<Definition> {
@Override
public Definition deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
throws IOException, JsonProcessingException {
Definition definition = new Definition();
String name = jsonParser.readValueAs(String.class);
definition.setName(name);
return definition;
}
}
Amostra principalpublic class App
{
public static void main( String[] args ) throws IOException {
String sampleData = "{\"type\":\"form\",\"definition\":\"super\",\"formName\":\"FormName\"}";
ObjectMapper mapper = new ObjectMapper();
Definition definition = mapper.readValue(sampleData, Definition.class);
System.out.println(definition);
}
}
A execução do aplicativo principal de exemplo gerará uma exceção:
Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Can not instantiate value of type [simple type, class jp.co.worksap.model.Definition] from String value ('super'); no single-String constructor/factory method (through reference chain: jp.co.worksap.model.FormDefinition["definition"])
que parece usarAsPropertyTypeDeserializer
desserializar odefinition
Campo deFormDefinition
classe em vez do desserializador anotadoDefinitionDeserializer
.
Eu acho que a parte mais complicada aqui é que o campo que eu quero usar desserializador personalizado também é o tipo deDefinition
qual usando@JsonTypeInfo
para resolver os problemas polimórficos.
Existe alguma maneira de usá-los juntos? Obrigado.