xmlmapper new deserializar java xml arrays jackson deserialization

new - xml to object java



jackson xml deserializar array en línea (1)

Cómo deserializar ese extraño XML. En mi opinión, la utilería-entidad falta (alrededor de las propiedades), pero no puedo cambiar la fuente de este xml (un servicio web).

<parents> <parent name="first"> <description><![CDATA[Description for the first-Entity]]></description> <prop name="level"> <value><![CDATA[1]]></value> </prop> <prop name="enabled"> <value><![CDATA[true]]></value> </prop> <prop name="version"> <value><![CDATA[1.0-beta3]]></value> </prop> </parent> <parent name="second">...</parent> ... </parents>

Mis entidades son

public class Test { @Test public void deserializerTest() throws JsonParseException, JsonMappingException, IOException { ObjectMapper om = new XmlMapper(); List<Parent> xml = om.readValue(new File("./test.xml"), new TypeReference<List<Parent>>() {}); } } public class Prop { @JacksonXmlProperty(isAttribute = true) public String name; @JacksonXmlText public String value; } @JacksonXmlRootElement public class Parent { @JacksonXmlProperty(isAttribute = true) public String name; public String description; // 1. alternative public List<Prop> prop; // 2. alternative with Map @JsonDeserialize(using = PropDeser.class public Map<String, String> prop; } public static class PropDeser extends JsonDeserializer<Map<String, String>> { @Override public Map<String, String> deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { Map<String, String> ret = new HashMap<String, String>(); boolean eof = false; while (jp.hasCurrentToken()) { JsonToken t = jp.getCurrentToken(); switch (t) { case END_OBJECT: if (eof) { return ret; } eof = true; break; case VALUE_STRING: ret.put(jp.getCurrentName(), jp.getText()); break; default: eof = false; break; } jp.nextValue(); } return null; } }

1. Alternativa

crea una excepción ''No se puede crear una instancia del valor del tipo [tipo simple, clase my.test.Prop] de JSON String; no hay un único constructor de String / método de fábrica (a través de la cadena de referencia: my.test.Parent ["prop"]) ''

No quiero una simple lista de cadenas. Necesito ambos: nombre y valor. Entonces llegué a la idea de usar un Map<String, String> creando un deserializador propio ...

2. Alternativa

El error parece ser el método PropDeser.deserialize () consume la etiqueta de cierre de parent.

java.lang.NullPointerException at com.fasterxml.jackson.databind.deser.impl.BeanPropertyMap.find(BeanPropertyMap.java:160) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:287) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:112) at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:226) at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:203) at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:23) at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2575) at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:1766) at my.test.Test.deserializerTest(Test.java:57)

¿Existe la posibilidad de iterar hacia atrás en la secuencia XML ? ¿Cómo puede saber el método cuándo detenerse? Ahora tengo una pista.


Debería ser posible manejar el estilo " @JacksonXmlElementWrapper(useWrapping=false) " de elementos de lista con Jackson XML module 2.1, con @JacksonXmlElementWrapper(useWrapping=false) .

La estructura debería ser algo como esto:

@JacksonXmlRootElement(localName="parents") public class Parents { @JacksonXmlElementWrapper(useWrapping=false) public List<Parent> parent; } public class Parent { @JacksonXmlProperty(isAttribute=true) public String name; public String description; @JacksonXmlElementWrapper(useWrapping=false) public List<Prop> prop; } public class Prop { @JacksonXmlProperty(isAttribute=true) public String name; public String value; }

entonces tu solución fue bastante cercana.

Tenga en cuenta que si se usan clases internas, deben tener ''static'' en la declaración. Probé esto con 2.1.4, y funciona para mí.