java json serialization jaxb moxy

java - Serialización de nulos y cadenas vacías en JSON dinámico



serialization jaxb (1)

Hay cosas que quizás quieras probar.

Primero, intente utilizar @XmlElement(nillable=true) lugar de la anotación XmlNullPolicy o establezca el parámetro emptyNodeRepresentsNull .

En segundo lugar, es posible que desee escribir su propio XmlAdapter que hará más o menos lo mismo: unmarshall empty string to null. La principal diferencia es que también puede configurar manualmente qué campos se desmarcarán con su adaptador y cuáles no, por lo tanto, conservará el comportamiento actual. Consulte esta answer de Blaise Doughan para ver cómo XmlAdapter un XmlAdapter personalizado a su configuración.

Tercero, que yo sepa, Jackson no tiene este problema. Vea esta respuesta de esta página wiki sobre cómo configurar un deserializador personalizado para un campo en caso de que lo haga.

Tengo este contenido JSON:

{"color":null}

Y quiero hacer que estos objetos Java salgan de él (y viceversa):

Container |- List<Entry> entries |- Entry |- String key = "color" |- String value = null

Mi solución actual siempre deserializa "color":null a una cadena vacía . Encontré otras soluciones, que en su lugar deserializarán String null o vacío para null .

¿Cómo puedo obtener MOXy (o cualquier otra implementación de jaxb) para deserializar null como cadenas vacías y vacías para vaciar Cadenas?

Estoy usando este código:

import java.io.ByteArrayOutputStream; import java.util.*; import javax.xml.bind.*; import javax.xml.bind.annotation.*; import org.eclipse.persistence.internal.oxm.ByteArraySource; import org.eclipse.persistence.jaxb.JAXBContextProperties; import org.eclipse.persistence.oxm.annotations.*; import org.junit.*; class Container { @XmlVariableNode("key") List<Entry> entries = new ArrayList<Entry>(); } class Entry { @XmlTransient public String key; @XmlValue @XmlNullPolicy(nullRepresentationForXml=XmlMarshalNullRepresentation.XSI_NIL, xsiNilRepresentsNull=false) public String value; } public class D { /** THIS TEST FAILS!!! */ @Test public void unmarshallNull() throws Exception { Assert.assertEquals(null, unmarshall("xml", "<root><color xmlns:xsi=/"http://www.w3.org/2001/XMLSchema-instance/" xsi:nil=/"true/"/></root>")); Assert.assertEquals(null, unmarshall("json", "{/"color/":null}")); } /* All other tests are passing. */ @Test public void unmarshallEmpty() throws Exception { Assert.assertEquals("", unmarshall("xml", "<root><color></color></root>")); Assert.assertEquals("", unmarshall("json", "{/"color/":/"/"}")); } @Test public void unmarshallValue() throws Exception { Assert.assertEquals("red", unmarshall("xml", "<root><color>red</color></root>")); Assert.assertEquals("red", unmarshall("json", "{/"color/":/"red/"}")); } @Test public void marshallNull() throws Exception { Assert.assertEquals("<color xmlns:xsi=/"http://www.w3.org/2001/XMLSchema-instance/" xsi:nil=/"true/"/>", marshall("xml", null)); Assert.assertEquals("{/"color/":null}", marshall("json", null)); } @Test public void marshallEmpty() throws Exception { Assert.assertEquals("<color></color>", marshall("xml", "")); Assert.assertEquals("{/"color/":/"/"}", marshall("json", "")); } @Test public void marshallValue() throws Exception { Assert.assertEquals("<color>red</color>", marshall("xml", "red")); Assert.assertEquals("{/"color/":/"red/"}", marshall("json", "red")); } private static String marshall(String format, String value) throws JAXBException { // prepare JAXBContext jc = JAXBContext.newInstance(Container.class); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(JAXBContextProperties.MEDIA_TYPE, "application/"+format); marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE); marshaller.setProperty(JAXBContextProperties.JSON_INCLUDE_ROOT, false); // define example data Container detail = new Container(); Entry entry = new Entry(); entry.key = "color"; entry.value = value; detail.entries.add(entry); // marshall ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); marshaller.marshal(detail, outputStream); return outputStream.toString(); } private static String unmarshall(String format, String raw) throws JAXBException { // prepare JAXBContext jc = JAXBContext.newInstance(Container.class); Unmarshaller unmarshaller = jc.createUnmarshaller(); unmarshaller.setProperty(JAXBContextProperties.MEDIA_TYPE, "application/"+format); unmarshaller.setProperty(JAXBContextProperties.JSON_INCLUDE_ROOT, false); // unmarshall Container container = unmarshaller.unmarshal(new ByteArraySource(raw.getBytes()), Container.class).getValue(); return container.entries.get(0).value; } }

Funciona para XML pero falla para JSON:

Test failure: unmarshallNull java.lang.AssertionError: expected:<null> but was:<>

También configuré MOXy como mi proveedor jaxb para el paquete relevante ( jaxb.properties ):

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

Estoy usando MOXy 2.22.1 y Java8 (pero el mismo comportamiento con 2.18 , 2.19 , 2.20 , 2.21 , 2.22 ). Mi Maven pom.xml :

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>x</groupId> <artifactId>x</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-moxy</artifactId> <version>2.22.1</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>