java - jsonserialize - jsonvalue jackson
Deserializador personalizado Jackson para un campo con tipos polimórficos (1)
Actualizar:
Intenté depurar en el código fuente de Jackson y descubrir que en el método
deserialize(JsonParser jp, DeserializationContext ctxt) de
SettableBeanProperty.java
cuando _valueTypeDeserializer no es nulo, nunca utilizará _valueDeserializer .
¿Es esta una suposición correcta de que TypeDeserializer debería ser más apropiado que ValueDeserializer?
Estoy tratando de usar @JsonDeserialize para definir deserializador personalizado para un campo con tipos polimórficos. Puedo tener éxito al usar @JsonDeserialize y @JsonTypeInfo separado. Pero cuando los uso juntos, parece que la anotación @JsonDeserialize se ignora.
Aquí está mi jerarquía de clases:
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.java
public 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.java
public 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;
}
}
Muestra principal
public 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);
}
}
Ejecutar la aplicación principal de ejemplo lanzará una excepción:
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 utilizar AsPropertyTypeDeserializer para deserializar el campo de definition de la clase FormDefinition lugar del deserializador anotado DefinitionDeserializer .
Creo que la parte difícil aquí es que el campo que deseo usar deserializador personalizado es también un tipo de Definition que usa @JsonTypeInfo para resolver los problemas polimórficos.
¿Hay alguna manera de usarlos juntos? Gracias.
Jackson procesa @JsonTypeInfo antes de elegir qué Deserializer usar, probablemente porque la elección de Deserializer podría depender generalmente del tipo. Sin embargo, puede deshabilitar esto fácilmente por campo de la misma manera que especifica Deserializer personalizado, anotando el campo directamente:
@JsonDeserialize(using = DefinitionDeserializer.class)
@JsonTypeInfo(use = JsonTypeInfo.Id.NONE)
private Definition definition;