【问题标题】:Create Marshaller for JSON from unknown JAXBContext (XML)从未知的 JAXBContext (XML) 为 JSON 创建 Marshaller
【发布时间】:2014-11-21 16:24:35
【问题描述】:

我必须使用一个库,它只给我一个 JAXBContext 来将 XML 数据编组和解组到 Java 对象。此外,我从未见过 XML:只有 JAXB 对象被传递给我。我现在需要的是将这些对象转换为 JSON,而不是 XML。

有没有办法从给定的 JAXBContext 创建可用于生成 JSON 输出的编组器?

情况是我不仅在转换数据。我还有作用于 XML 和 JSON 之间的 Java 对象的逻辑(并操作数据)。也是一种双向转换。 JAXBContext 是我拥有的关于 XML 和 Java 对象之间转换的信息——我的目的是重用此上下文信息,而不必使用不同于 JAXB 的第二种技术实现第二次转换。 JAXBContext(及其 Java 对象)已经拥有有关 XML 结构的信息; JAXB 自动识别该结构是使用它的节省时间的原因。

【问题讨论】:

  • 如何尝试先转换 XML,然后转换为 Json,如 XML to Json ???或者可能需要实现合适的 xml 解析器来将 xml 内容转换为所需的 Json 格式!
  • 问题是我不仅在转换数据。我还有必须作用于 XML 和 JSON 之间的 Java 对象的逻辑。也是一种双向转换。 JAXBContext 是我拥有的关于 XML 和 Java 对象之间转换的信息——我的目的是重用该上下文信息,而不必使用不同于 JAXB 的第二种技术来实现第二次转换。 JAXBContext(及其 Java 对象)已经拥有有关 XML 结构的信息; JAXB 自动识别该结构是使用它的节省时间的原因。
  • 我也从未见过 XML。只有 JAXB 对象传递给我。 (将此添加到问题中)

标签: java json jaxb marshalling


【解决方案1】:

如果您的 JAXB 类只使用基本注解,您可以查看JacksonJAXBAnnotations,允许 Jackson 映射器识别 JAXN 注解。您只需要四行代码(在最简单的编组情况下)。

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

您可以在上面的链接中查看所有受支持的注释。您需要的 Maven 工件是

<dependency>
    <groupId>com.fasterxml.jackson.module</groupId>
    <artifactId>jackson-module-jaxb-annotations</artifactId>
    <version>2.4.0</version>
</dependency>
  • 查看jackson-module-jaxb-annotations 的github - 请注意,此工件依赖于jackson-core 和jackson-databind。因此,如果您不使用 maven,则需要确保也下载这些工件

简单示例:

JAXB 类

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "hello",
    "world"
})
@XmlRootElement(name = "root")
public class Root {

    @XmlElement(required = true)
    protected String hello;
    @XmlElement(required = true)
    protected String world;

    // Getters and Setters
}

XML

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <hello>JAXB</hello>
    <world>Jackson</world>
</root>

测试

public class TestJaxbJackson {
    public static void main(String[] args) throws Exception {
        JAXBContext context = JAXBContext.newInstance(Root.class);
        Unmarshaller unmarshaller = context.createUnmarshaller();
        InputStream is = TestJaxbJackson.class.getResourceAsStream("test.xml");
        Root root = (Root)unmarshaller.unmarshal(is);
        System.out.println(root.getHello() + " " + root.getWorld());

        ObjectMapper mapper = new ObjectMapper();
        JaxbAnnotationModule module = new JaxbAnnotationModule();
        mapper.registerModule(module);
        mapper.writeValue(System.out, root);
    }
}

结果

{"hello":"JAXB","world":"Jackson"}

更新

另见this post。看起来 MOXy 也提供了这种支持。

【讨论】:

  • 效果很好!是否可以仅通过配置 Jackson 来更改 JSON 表示?请记住:我没有对带有注释的 Java 类的写访问权。在我当前的设置中(我只需要包含测试的最后四行)output 遗憾地包含对象元素,例如“范围”、“全局范围”和“类型替换”。我想省略这些细节,只输出数据(名称、属性和元素内容)。这可能吗?这是否足以让传入的 JSON 再次传输到 JAXBElements?
  • 不确定额外的元素。但是对于解组,请查看 ObjectMapper.readValue(...) 解组的方法
  • 这似乎不是双向转换:code,input,例外:Caused by: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "name" (class net.opengis.wps.v_1_0_0.GetCapabilities), not marked as ignorable (3 known properties: "language", "AcceptVersions", "service"])
  • 这是因为那些不属于您的 jaxb 类的额外属性。解组适用于上面的示例。我不太确定如何摆脱这些。
  • 尝试使用new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);创建ObjectMapper
猜你喜欢
  • 2023-04-06
  • 2011-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多