library example databind json jackson

databind - spring jackson json example



DeserializaciĆ³n de Jackson Json, ignorar el elemento raĆ­z de json (3)

¿Cómo ignorar la etiqueta principal de json?

Aquí está mi json

String str = "{/"parent/": {/"a/":{/"id/": 10, /"name/":/"Foo/"}}}";

Y aquí está la clase a mapear de json.

public class RootWrapper { private List<Foo> foos; public List<Foo> getFoos() { return foos; } @JsonProperty("a") public void setFoos(List<Foo> foos) { this.foos = foos; } }

Aquí está la prueba de clase pública JacksonTest {

@Test public void wrapRootValue() throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.configure(DeserializationConfig.Feature.UNWRAP_ROOT_VALUE, true); mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false); String str = "{/"parent/": {/"a/":{/"id/": 10, /"name/":/"Foo/"}}}"; RootWrapper root = mapper.readValue(str, RootWrapper.class); Assert.assertNotNull(root); }

Me sale el error ::

org.codehaus.jackson.map.JsonMappingException: Root name ''parent'' does not match expected (''RootWrapper'') for type [simple type, class MavenProjectGroup.mavenProjectArtifact.RootWrapper]

Encontré la solución dada por la anotación de Jackson ::

(a) Annotate you class as below @JsonRootName(value = "parent") public class RootWrapper { (b) It will only work if and only if ObjectMapper is asked to wrap. ObjectMapper mapper = new ObjectMapper(); mapper.configure(DeserializationConfig.Feature.UNWRAP_ROOT_VALUE, true);

¡¡Trabajo hecho!!

Otro inconveniente con la forma de deserialización de Jackson :(

si ''DeserializationConfig.Feature.UNWRAP_ROOT_VALUE configured'', desenvuelve todos los jsons, aunque mi clase no está anotada con @JsonRootName (value = "rootTagInJson"), no está cargada.

Deseo desenvolver la etiqueta raíz solo si la clase está anotada con @JsonRootName, de lo contrario, no desenvolver.

A continuación se muestra el caso de uso para desenvolver la etiqueta raíz.

########################################################### Unwrap only if the class is annotated with @JsonRootName. ############################################################

Hice un pequeño cambio en el código fuente de ObjectMapper de Jackson y creé una nueva versión de jar. 1. Coloque este método en ObjectMapper

// Ash:: Wrap json if the class being deserialized, are annotated // with @JsonRootName else do not wrap. private boolean hasJsonRootName(JavaType valueType) { if (valueType.getRawClass() == null) return false; Annotation rootAnnotation = valueType.getRawClass().getAnnotation(JsonRootName.class); return rootAnnotation != null; } 2. Edit ObjectMapper method :: Replace cfg.isEnabled(DeserializationConfig.Feature.UNWRAP_ROOT_VALUE) with hasJsonRootName(valueType) 3. Build your jar file and use it.


Como actualización de la publicación de Seagabond, si desea tener el mismo efecto cuando escribe valores de parámetros, puede anular los métodos de escritura adicionales.

@Component public class ObjectMapper extends com.fasterxml.jackson.databind.ObjectMapper { private void autoconfigureFeatures(Object value) { JavaType javaType = _typeFactory.constructType(value.getClass()); autoconfigureFeatures(javaType); } private void autoconfigureFeatures(JavaType javaType) { Annotation rootAnnotation = javaType.getRawClass().getAnnotation(JsonRootName.class); this.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, rootAnnotation != null); } @Override public void writeValue(DataOutput out, Object value) throws IOException { autoconfigureFeatures(value); super.writeValue(out, value); } @Override public void writeValue(Writer w, Object value) throws IOException, JsonGenerationException, JsonMappingException { autoconfigureFeatures(value); super.writeValue(w, value); } @Override public byte[] writeValueAsBytes(Object value) throws JsonProcessingException { autoconfigureFeatures(value); return super.writeValueAsBytes(value); } @Override public String writeValueAsString(Object value) throws JsonProcessingException { autoconfigureFeatures(value); return super.writeValueAsString(value); } @Override protected Object _readMapAndClose(JsonParser jsonParser, JavaType javaType) throws IOException, JsonParseException, JsonMappingException { autoconfigureFeatures(javaType); return super._readMapAndClose(jsonParser, javaType); } }


Experimenté un problema similar al desarrollar una aplicación relajante en la primavera. Tuve que admitir una API muy heterogénea, otra parte tenía elementos raíz y otra no. No pude encontrar una solución mejor que configurar esta propiedad en tiempo real. Es una pena que no haya soporte para el desenvolvimiento de elementos raíz por clase en Jackson. De todos modos, alguien puede encontrar esto útil.

@Component public class ObjectMapper extends com.fasterxml.jackson.databind.ObjectMapper { private void autoconfigureFeatures(JavaType javaType) { Annotation rootAnnotation = javaType.getRawClass().getAnnotation(JsonRootName.class); this.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, rootAnnotation != null); } @Override protected Object _readMapAndClose(JsonParser jsonParser, JavaType javaType) throws IOException, JsonParseException, JsonMappingException { autoconfigureFeatures(javaType); return super._readMapAndClose(jsonParser, javaType); } }


Un ejemplo tomado de TestRootName.java en https://github.com/FasterXML/jackson-databind puede ser una mejor manera de hacerlo. Específicamente utilizando withRootName (""):

private ObjectMapper rootMapper() { ObjectMapper mapper = new ObjectMapper(); mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true); mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true); return mapper; } public void testRootUsingExplicitConfig() throws Exception { ObjectMapper mapper = new ObjectMapper(); ObjectWriter writer = mapper.writer().withRootName("wrapper"); String json = writer.writeValueAsString(new Bean()); assertEquals("{/"wrapper/":{/"a/":3}}", json); ObjectReader reader = mapper.reader(Bean.class).withRootName("wrapper"); Bean bean = reader.readValue(json); assertNotNull(bean); // also: verify that we can override SerializationFeature as well: ObjectMapper wrapping = rootMapper(); json = wrapping.writer().withRootName("something").writeValueAsString(new Bean()); assertEquals("{/"something/":{/"a/":3}}", json); json = wrapping.writer().withRootName("").writeValueAsString(new Bean()); assertEquals("{/"a/":3}", json); bean = wrapping.reader(Bean.class).withRootName("").readValue(json); assertNotNull(bean); }