web-dev-qa-db-fra.com

Mappage JAXB vers JSON

J'ai écrit un service JAX-RS (Jersey) REST, qui accepte les messages XML au format ONIX XML. En général, j'ai généré toutes les classes requises pour la liaison JAXB à partir du schéma donné avec xjc. Il y a plus de 500 classes au total et je ne peux pas les modifier.

Maintenant, quand j'ai un objet mappé JAXB, je dois le stocker dans la base de données. Je travaille avec mongoDb, donc le format du message doit être JSON. J'ai essayé d'utiliser Jackson avec le module JAXB pour convertir un objet JAXB en JSON, ce qui fonctionne très bien avec le stockage des données. Mais lorsque j'essaie de reconvertir le JSON en objet JAXB, il lève une exception liée d'une manière ou d'une autre au JAXBElement. Dans Google, j'ai découvert que le JAXBElement n'est pas pris en charge dans Jackson et je dois contourner ce problème. Mais je ne peux pas le faire parce que je ne peux pas modifier les classes générées par JAXB.

Existe-t-il un moyen de mapper des objets JAXB en JSON avec d'autres moyens, mais qui suivra toute la spécification JAXB afin que je n'ai aucun problème à l'avenir à convertir de JSON en objet JAXB et visa vera?

13
Artem Moskalev

Remarque: Je suis le EclipseLink JAXB (MOXy) chef de file et membre du groupe d'experts JAXB (JSR-222) .

Si vous ne pouvez pas le faire avec Jackson, votre cas d'utilisation fonctionnera avec MOXy.

Modèle Java

Foo

Voici un exemple de classe qui contient un champ de type JAXBElement.

import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;

@XmlAccessorType(XmlAccessType.FIELD)
public class Foo {

    @XmlElementRef(name="bar")
    private JAXBElement<Bar> bar;

}

Barre

public class Bar {

}

ObjectFactory

import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
import javax.xml.namespace.QName;

@XmlRegistry
public class ObjectFactory {

    @XmlElementDecl(name = "bar")
    public JAXBElement<Bar> createBar(Bar bar) {
        return new JAXBElement<Bar>(new QName("bar"), Bar.class, bar);
    }

}

Code de démonstration autonome

Vous trouverez ci-dessous un code de démonstration que vous pouvez exécuter dans Java SE pour voir que tout fonctionne:

Démo

import Java.util.*;
import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;

import org.Eclipse.persistence.jaxb.JAXBContextProperties;

public class Demo {

    public static void main(String[] args) throws Exception {
        Map<String, Object> properties = new HashMap<String, Object>(2);
        properties.put(JAXBContextProperties.MEDIA_TYPE, "application/json");
        properties.put(JAXBContextProperties.JSON_INCLUDE_ROOT, false);
        JAXBContext jc = JAXBContext.newInstance(new Class[] {Foo.class, ObjectFactory.class}, properties);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        StreamSource json = new StreamSource("src/forum19158056/input.json");
        Foo foo = unmarshaller.unmarshal(json, Foo.class).getValue();

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(foo, System.out);
    }

}

input.json/Output

{"bar" : {} }

Fonctionnement avec JAX-RS

Les liens suivants vous aideront à tirer parti de MOXy dans un service JAX-RS:

17
bdoughan

Puisque vous utilisez Jackson, vous pouvez construire un ObjectMapper avec le JaxbAnnotationModule et écrire la valeur. Voici du code pour écrire un objet annoté JAXB dans le système.

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JaxbAnnotationModule());
        mapper.writeValue(System.out, jaxbObject);

Cette approche fonctionnera également sur Glassfish car elle n'utilise pas le fournisseur donné par le conteneur, ce qui provoquerait ClassNotFoundException selon GLASSFISH-21141

8