java - MOXy 对 org.glassfish.json.JsonProviderImpl 的依赖?还有一个问题
问题描述
我正在尝试做一些我认为很简单的事情,那就是使用 JSON 来保存一个 POJO 容器,其中包含各种属性。
在阅读了关于编组/解组 JSON 的各种方法之后,我认为 MOXy 将是最好的方法,因为它似乎能够处理非 JAXB 注释的 POJO。我正在使用 MOXy 2.7.3。
但是,我遇到了两个问题:
我正在使用具有以下依赖项的 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 依赖项?
我需要
@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