JAXB Сопоставление JSON

Я написал службу REST JAX-RS (Джерси), которая принимает XML-сообщения формата ONIX XML. Как правило, я создал все необходимые классы для привязки JAXB из данной схемы с xjc. В общей сложности более 500 классов, и я не могу их модифицировать.

Теперь, когда у меня есть JAXB-сопоставленный объект, мне нужно сохранить его в базе данных. Я работаю с mongoDb, поэтому формат сообщения должен быть JSON. Я попытался использовать Jackson с модулем JAXB для преобразования JAXB-объекта в JSON, который отлично работает с сохранением данных. Но когда я пытаюсь преобразовать JSON обратно в объект JAXB, он создает исключение, связанное каким-то образом с JAXBElement. В google я узнал, что JAXBElement не поддерживается в Джексоне, и мне нужно решить эту проблему. Но я не могу это сделать, потому что я не могу изменять классы, созданные JAXB.

Есть ли способ сопоставить объекты JAXB в JSON с некоторыми другими средствами, но которые будут следовать всей спецификации JAXB, так что у меня нет проблем в будущем конвертировать JSON в объект JAXB и визу vera?

Ответ 1

Примечание. Я EclipseLink JAXB (MOXy) и член JAXB (JSR-222).

Если вы не можете сделать это с Джексоном, вы используете случай, который будет работать с MOXy.

Модель Java

Foo

Вот образец класса, который содержит поле типа JAXBElement.

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

@XmlAccessorType(XmlAccessType.FIELD)
public class Foo {

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

}

Bar

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);
    }

}

Автономный демонстрационный код

Ниже приведен какой-то демо-код, который вы можете запустить в Java SE, чтобы увидеть, что все работает:

Demo

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/выход

{"bar" : {} }

Работа с JAX-RS

Следующие ссылки помогут вам использовать MOXy в сервисе JAX-RS:

Ответ 2

Поскольку вы используете Jackson, вы можете построить ObjectMapper с помощью JaxbAnnotationModule и выписать значение. Ниже приведен некоторый код для записи аннотированного объекта JAXB в систему.

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

Этот подход также будет работать на Glassfish, поскольку он не использует провайдера, предоставленного контейнером, что вызовет ClassNotFoundException в соответствии с GLASSFISH-21141