Sérialiser les nuls et les chaînes vides dans le JSON dynamique
j'ai ce json-Content:
{"color":null}
et je veux en faire des objets Java (et vice-versa):
Container
|- List<Entry> entries
|- Entry
|- String key = "color"
|- String value = null
ma solution actuelle désérialise toujours "color":null
en une chaîne vide . J'ai trouvé d'autres solutions, qui vont plutôt desérialiser null
ou une chaîne vide en null
.
Comment faire pour que MOXy (ou toute autre implémentation jaxb) désérialise null
comme null
et cordes vides pour cordes vides?
j'utilise ce code:
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;
}
}
il fonctionne pour XML mais ne fonctionne pas pour JSON:
Test failure: unmarshallNull
java.lang.AssertionError: expected:<null> but was:<>
j'ai aussi configuré MOXy comme mon fournisseur jaxb pour le paquet concerné ( jaxb.properties
):
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
j'utilise MOXy 2.22.1
et Java8 (mais même comportement avec 2.18
, 2.19
, 2.20
, 2.21
, 2.22
). My 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>
1 réponses
il y a des choses que vous pourriez essayer.
essayez D'abord d'utiliser @XmlElement(nillable=true)
au lieu de XmlNullPolicy
annotation ou paramétrage du paramètre emptyNodeRepresentsNull
.
Deuxièmement, vous pourriez vouloir écrire votre propre XmlAdapter
qui fera à peu près la même chose - unmarshall chaîne vide à null. La principale différence est que vous pouvez également configurer manuellement les champs qui seront désactivés avec votre adaptateur et qui ne le seront pas, le comportement actuel. Référez-vous à cette réponse de Blaise Doughan pour voir comment faire un câblage personnalisé XmlAdapter
à votre configuration.
Troisièmement, autant que je sache Jackson n'a pas ce problème. Voir cette réponse ot cette page du wiki sur la façon de configurer une coutume deserializer pour un champ dans le cas où il n'.