jsonunwrapped jsonsubtypes jsonserialize jsonproperty jsongetter jsondeserialize for example java json spring jackson

java - jsonsubtypes - De-serialización de JSON al modelo de objeto polimórfico usando la anotación Spring y JsonTypeInfo



jsonproperty for class (6)

El método registerSubtypes() funciona!

@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="type") public interface Geometry { //... } public class Point implements Geometry{ //... } public class Polygon implements Geometry{ //... } public class LineString implements Geometry{ //... } GeoJson geojson= null; ObjectMapper mapper = new ObjectMapper(); mapper.disable(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES); mapper.registerSubtypes(Polygon.class,LineString.class,Point.class); try { geojson=mapper.readValue(source, GeoJson.class); } catch (IOException e) { e.printStackTrace(); }

Nota 1: Utilizamos la interfaz y las clases de implementación. Si desea que jackson des-serialice las clases según sus clases de implementación, debe registrarlas todas utilizando el método "registerSubtypes" de ObjectMapper.

Nota2: Además, usa "@JsonTypeInfo (use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property =" type ")" como anotación en su interfaz.

También puede definir el orden de las propiedades cuando el asignador escribe un valor de su POJO como json.

Esto lo puedes hacer usando la siguiente anotación.

@JsonPropertyOrder({"type","crs","version","features"}) public class GeoJson { private String type="FeatureCollection"; private List<Feature> features; private String version="1.0.0"; private CRS crs = new CRS(); ........ }

¡Espero que esto ayude!

Tengo el siguiente modelo de objeto en mi aplicación web Spring MVC (v3.2.0.RELEASE):

public class Order { private Payment payment; } @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = As.WRAPPER_OBJECT) @JsonSubTypes.Type(name = "creditCardPayment", value = CreditCardPayment.class) public interface Payment {} @JsonTypeName("creditCardPayment") public class CreditCardPayment implements Payment {}

Cuando serializo la clase Order a JSON, obtengo el siguiente resultado (que es exactamente lo que quiero):

{ "payment" : { "creditCardPayment": { ... } }

Desafortunadamente, si tomo el JSON anterior e intento dessializarlo nuevamente en mi modelo de objeto, obtengo la siguiente excepción:

No se pudo leer JSON: No se pudo resolver el tipo de identificación ''creditCardPayment'' en un subtipo de [tipo simple, Pago de clase] en [Fuente: org.apache.catalina.connector.CoyoteInputStream@19629355; línea: 1, columna: 58] (a través de la cadena de referencia: Orden ["pago"]); la excepción anidada es com.fasterxml.jackson.databind.JsonMappingException: No se pudo resolver el tipo de identificación ''creditCardPayment'' en un subtipo de [tipo simple, clase Pago] en [Fuente: org.apache.catalina.connector.CoyoteInputStream@19629355; línea: 1, columna: 58] (a través de la cadena de referencia: Orden ["pago"])

Mi aplicación se configura a través de Spring JavaConf, de la siguiente manera:

@Configuration @EnableWebMvc public class AppWebConf extends WebMvcConfigurerAdapter { @Bean public ObjectMapper objectMapper() { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.setSerializationInclusion(Include.NON_NULL); objectMapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false); return objectMapper; } @Bean public MappingJackson2HttpMessageConverter mappingJacksonMessageConverter() { MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); converter.setObjectMapper(objectMapper()); return converter; } @Bean public Jaxb2RootElementHttpMessageConverter jaxbMessageConverter() { return new Jaxb2RootElementHttpMessageConverter(); } @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { converters.add(jaxbMessageConverter()); converters.add(mappingJacksonMessageConverter()); } }

Para las pruebas, tengo un controlador con 2 métodos, uno devuelve una solicitud de pedido GET de HTTP (este funciona) y uno que acepta un pedido a través de un POST de HTTP (este falla), por ejemplo

@Controller public class TestController { @ResponseBody @RequestMapping(value = "/test", method = RequestMethod.GET) public Order getTest() {} @RequestMapping(value = "/test", method = RequestMethod.POST) public void postTest(@RequestBody order) {} }

He intentado todas las sugerencias de las diversas discusiones sobre SO pero hasta ahora no he tenido suerte. ¿Alguien puede detectar lo que estoy haciendo mal?


En mi caso, había agregado defaultImpl = SomeClass.class a @JsonTypeInfo y estaba intentando convertirlo en SomeClass2.class


Encontró el mismo error y usó el equivalente del JSON a continuación (en lugar de CreditCardPayment utilizó mi nombre de clase) como la entrada para el deserializador y funcionó:

{ "type": "CreditCardPayment", ... }


Intente registrar el subtipo utilizando ObjectMapper.registerSubtypes lugar de usar anotaciones


La respuesta de Rashmin funcionó, y encontré una forma alternativa de evitar com.fasterxml.jackson.databind.JsonMappingException: Could not resolve type id into a subtype of Blah problema com.fasterxml.jackson.databind.JsonMappingException: Could not resolve type id into a subtype of Blah sin necesidad de usar registerSubtypes . Lo que puede hacer es agregar la siguiente anotación a la clase principal:

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "type")

Tenga en cuenta que la diferencia es JsonTypeInfo.Id.CLASS lugar de JsonTypeInfo.Id.NAME . El inconveniente es que el JSON creado contendrá el nombre completo de la clase, incluido el espacio de nombres completo. La ventaja es que no tiene que preocuparse por registrar subtipos.


Tuve un problema similar mientras trabajaba en un servicio basado en dropwizard. No entiendo completamente por qué las cosas no me funcionaron de la misma manera que funciona el código de dropwizard, pero sé por qué el código en la publicación original no funciona. @JsonSubTypes quiere una matriz de subtipos, no un solo valor. Así que si reemplaza la línea ...

@JsonSubTypes.Type(name = "creditCardPayment", value = CreditCardPayment.class)

con...

@JsonSubTypes({ @JsonSubTypes.Type(name = "creditCardPayment", value = CreditCardPayment.class) })

Creo que su código funcionará.

Para aquellos que tienen este mismo mensaje de error emergente, es posible que tenga un problema con los subtipos que se están descubriendo. Intente agregar una línea como la de arriba o busque un problema con el descubrimiento de las clases que tienen la etiqueta @JsonTypeName en ellas.