首页 > 解决方案 > MOXy 对 org.glassfish.json.JsonProviderImpl 的依赖?还有一个问题

问题描述

我正在尝试做一些我认为很简单的事情,那就是使用 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>
    

但是,如果我不包括对 GlassFish JAR 的这种依赖:

    <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 依赖项?

  1. 我需要@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 https://stackoverflow.com/questions/6963996/can-i-replace-jaxb-properties-with-code 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

标签: javajsonmoxy

解决方案


推荐阅读