I posted this question on Stackoverflow first, but now I'm a bit unsure, whether it's a bug in MOXy or not.
I have this JSON-Content:
And I want to make these Java-Objects out of it (and vice-versa):
Container
|- List<Entry> entries
|- Entry
|- String key = "color"
|- String value = null
My current solution always deserializes "color":null to an empty String.
Serialization works fine.
How can I get MOXy / jaxb to always deserialize null as null?
I am using this 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("{\"color\":null}"));
}
/* All other tests are passing. */
@Test
public void unmarshallEmpty() throws Exception {
Assert.assertEquals("", unmarshall("{\"color\":\"\"}"));
}
@Test
public void unmarshallValue() throws Exception {
Assert.assertEquals("red", unmarshall("{\"color\":\"red\"}"));
}
@Test
public void marshallNull() throws Exception {
Assert.assertEquals("{\"color\":null}", marshall(null));
}
@Test
public void marshallEmpty() throws Exception {
Assert.assertEquals("{\"color\":\"\"}", marshall(""));
}
@Test
public void marshallValue() throws Exception {
Assert.assertEquals("{\"color\":\"red\"}", marshall("red"));
}
private static String marshall(String value) throws JAXBException {
// prepare
JAXBContext jc = JAXBContext.newInstance(Container.class);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(JAXBContextProperties.MEDIA_TYPE, "application/json");
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 raw) throws JAXBException {
// prepare
JAXBContext jc = JAXBContext.newInstance(Container.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
unmarshaller.setProperty(JAXBContextProperties.MEDIA_TYPE, "application/json");
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;
}
}
It fails:
Test failure: unmarshallNull
java.lang.AssertionError: expected:<null> but was:<>
I also configured MOXy as my jaxb-provider for the relevant package (jaxb.properties):
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
I'm using MOXy 2.22.1 and Java8 (but same behaviour with 2.18, 2.19, 2.20, 2.21, 2.22). My Maven pom.xml:
<project xmlns="..." xmlns:xsi="..."
xsi:schemaLocation="...">
<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>