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>
28
demandé sur slartidan 2015-12-15 16:09:15

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'.

5
répondu Jeor Mattan 2017-05-23 11:45:24