xmlmapper new deserializar convert java xml jackson

new - xml string to object java jackson



Módulo Jackson xml: deserialización del tipo inmutable con una propiedad @JacksonXmlText (3)

Intente agregar un captador público para la propiedad. Creo que eso debería solucionar el problema de la deserialización.

@JsonRootName("asText") @Accessors(prefix = "_") public static class AsText { @JsonProperty("text") @JacksonXmlText @Getter private final String _text; public AsText(@JsonProperty("text") final String text) { _text = text; } public String getText() { return _text; } }

En realidad, funciona sin agregar un getter también, con estas versiones de Lombak & Jackson.

<dependencies> <dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-xml</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.18</version> </dependency> </dependencies>

Quiero serializar un tipo inmutable tanto como json como como xml:

El JSON serializado es como:

{ "text" : "... the text..." }

y el xml serializado es como:

<asText>_text_</asText>

(tenga en cuenta que el texto es el texto del elemento xml)

El objeto java es como:

@JsonRootName("asText") @Accessors(prefix="_") public static class AsText { @JsonProperty("text") @JacksonXmlText @Getter private final String _text; public AsText(@JsonProperty("text") final String text) { _text = text; } }

tenga cuidado de que la propiedad _text sea final (por lo que el objeto es inmutable) y se anota con @JacksonXmlText para ser serializado como el texto del elemento xml

Siendo el objeto inmutable, se necesita un constructor del texto y el argumento del constructor debe ser anotado con @JsonProperty

public AsText(@JsonProperty("text") final String text) { _text = text; }

Al serializar / deserializar a / desde JSON todo funciona bien ... el problema surge al serializar / deserializar a / desde XML:

// create the object AsText obj = new AsText("_text_"); // init the mapper XmlMapper mapper = new XmlMapper(); // write as xml String xml = mapper.writeValueAsString(obj); log.warn("Serialized Xml/n{}",xml); // Read from xml log.warn("Read from Xml:"); AsText objReadedFromXml = mapper.readValue(xml, AsText.class); log.warn("Obj readed from serialized xml: {}", objReadedFromXml.getClass().getName());

La excepción es:

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "" (class r01f.types.url.UrlQueryStringParam), not marked as ignorable (2 known properties: "value", "name"])

Parece que el módulo xml necesita que el constructor del objeto se anote como:

public AsText(@JsonProperty("") final String text) { _text = text; }

PERO esto ni siquiera funciona:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `test.types.SerializeAsXmlElementTextTest$AsText` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)

La anotación @JsonProperty("text") en el argumento del constructor es necesaria para deserializar de JSON

... cómo puedo hacer que esto funcione


Parece que la razón principal de su problema es que intenta utilizar la serialización JSON y XML al mismo tiempo pero con diferentes configuraciones. Lamentablemente, XmlMapper hereda de ObjectMapper y hereda toda la configuración específica de JSON (y puede anularla pero no puede borrarla con anotaciones específicas de XML), que es la razón de su conflicto. Parece que la forma más simple de @JsonAlias esto es usar la anotación @JsonAlias en el constructor. Es un poco hacky pero funciona. Aquí hay un ejemplo mínimo (sin Lombok) que funciona para mí:

@JsonRootName("asText") public static class AsText { @JsonProperty("text") @JacksonXmlText private final String _text; public AsText(@JsonAlias("") @JsonProperty("text") final String text) { _text = text; } @JsonIgnore public String getText() { return _text; } @Override public String toString() { return "AsText{" + "_text=''" + _text + ''/''' + ''}''; } }

Tenga en cuenta que también agregué @JsonIgnore al getter porque de lo contrario no obtuve el formato XML que solicitó (y puede hacer lo mismo usando Lombok''s onMethod como se describe en onX ).

Para una prueba simple:

public static void main(String[] args) throws IOException { // create the object AsText obj = new AsText("123_text_"); // init the mapper //ObjectMapper mapper = new ObjectMapper(); XmlMapper mapper = new XmlMapper(); // write as xml String xml = mapper.writeValueAsString(obj); System.out.println("Serialized Xml/n" + xml); // Read from xml AsText objReadedFromXml = mapper.readValue(xml, AsText.class); System.out.println("Read from Xml: " + objReadedFromXml); }

Obtengo el siguiente resultado:

Serialized Xml
<asText> 123_text _ </ asText>
Leer desde Xml: AsText {_text = ''123_text_''}


Tuve el mismo problema con el error "sin creador delegado ni basado en propiedades". En mi caso, era un problema con Immutables versión 2.5.6. Lo he corregido por versión anterior a la versión 2.5.5. La versión 2.5.6 está disponible en mvnrepository.com pero en la página oficial es la versión estable marcada como 2.5.5.