MOXy зависимость от org.glassfish.json.JsonProviderImpl?И еще один вопрос - PullRequest
0 голосов
/ 19 сентября 2018

Я пытаюсь сделать что-то, что мне показалось довольно простым, а именно использовать JSON для сохранения контейнера POJO с различными свойствами в нем.

После прочтения о различных способах маршалирования / демаршализации JSONбез всего, что связано с веб-сервисами, я подумал, что MOXy будет лучшим способом, поскольку он может обрабатывать аннотации без JAXB POJO.Я использую MOXy 2.7.3.

Однако я столкнулся с двумя проблемами:

  1. Я использую Maven со следующей зависимостью:

    <dependency>
        <groupId>org.eclipse.persistence</groupId>
        <artifactId>org.eclipse.persistence.moxy</artifactId>
        <version>2.7.3</version>
    </dependency>
    

Однако, если я не включу эту зависимость в JAR-файл GlassFish:

    <dependency>
        <groupId>org.glassfish</groupId>
        <artifactId>javax.json</artifactId>
        <version>1.1.2</version>
    </dependency>

Я получаю следующее исключение при попытке демонтажа (маршалинг работает нормально):

    Caused by: Exception [EclipseLink-25004] (Eclipse Persistence Services - 2.7.3.v20180807-4be1041): org.eclipse.persistence.exceptions.XMLMarshalException
    Exception Description: An error occurred unmarshalling the document
    Internal Exception: javax.json.JsonException: Provider org.glassfish.json.JsonProviderImpl not found
        at org.eclipse.persistence.exceptions.XMLMarshalException.unmarshalException(XMLMarshalException.java:122)
        at org.eclipse.persistence.internal.oxm.record.json.JsonStructureReader.parse(JsonStructureReader.java:148)
        ...

Почему MOXy нужна зависимость GlassFish JsonProviderImpl?

Мне нужно объявить @XmlRootElement в моем классе контейнера.Не уверен, почему, но это так, даже если я использую marshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, true);, который, кажется, по умолчанию.Если у меня нет @XmlRootElement, я получаю следующее исключение при попытке демонтировать (маршалинг работает отлично):

Caused by: Exception [EclipseLink-25008] (Eclipse Persistence Services - 2.7.3.v20180807-4be1041): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: A descriptor with default root element stringValue was not found in the project

Возможно, я просто запутался,но из документов видно, что MOXy может работать с POJO?

Вот пример кода, показывающего, что я делаю:

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.Reader;
import java.io.Writer;
import java.nio.file.Paths;
import java.time.ZonedDateTime;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

import org.eclipse.persistence.jaxb.JAXBContextFactory;
import org.eclipse.persistence.jaxb.MarshallerProperties;

public class MoxyTest
{
    public static void main(String[] args) throws Exception
    {
        // Create an instance of the container to be written/read with JSON
        TestContainer testContainer = new TestContainer();
        testContainer.stringValue = "test string";
        testContainer.intValue = 5;
        testContainer.zonedDateTimeValue = ZonedDateTime.now().minusMonths(1);

        // Note that JAXBContextFactory is specific to MOXy, this was done to avoid having to create a jaxb.properties
        // See /6847881/mogu-li-ya-zamenit-jaxb-properties-kodom and
        // https://stackoverflow.com/questions/28676613/set-moxy-as-jaxb-provider-without-properties-file-in-the-same-package
        JAXBContext jaxbContext = JAXBContextFactory.createContext(new Class[] {TestContainer.class}, null);

        Marshaller marshaller = jaxbContext.createMarshaller();
        // By default the marshaller will output XML, we have to tell it to use JSON instead
        marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/json");

        File dataFile = Paths.get("/temp", "datafile.json").toFile();
        Writer writer = new FileWriter(dataFile);
        marshaller.marshal(testContainer, writer);

        writer.close();

        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
        // By default the unmarshaller will try to read XML, we have to tell it to use JSON instead
        unmarshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/json");

        // Determine the location for the file which is used to persist the data

        if (dataFile.exists() && (dataFile.length() > 0))
        {
            Reader reader = new FileReader(dataFile);
            TestContainer readTestContainer = (TestContainer) unmarshaller.unmarshal(reader);

            System.out.println(readTestContainer.intValue);
            System.out.println(readTestContainer.stringValue);
            System.out.println(readTestContainer.zonedDateTimeValue);

            reader.close();
        }
    }
}

И тестовый контейнер (с @XmlRootElement):

import java.time.ZonedDateTime;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "testContainer")
public class TestContainer
{
    public String stringValue;
    public int intValue;
    public ZonedDateTime zonedDateTimeValue;
}

Обратите внимание, что для дополнительной удивительности, возможно, кто-то может ответить, почему ZonedDateTime будет правильно маршалировать, но не демаршировать (результат равен null)?Вот результаты запуска MoxyTest:

5
test string
null
...