tostringserializer jsonvalue jsonserialize example deserializer custom java json polymorphism jackson deserialization

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;