使用 Jackson API 和 JAXB 注释将 JSON 转换为 XML,反之亦然

2022-01-19 00:00:00 xml json java jackson jaxb

我正在尝试编写一个可以分别接受 XML 或 JSON 输入和输出 JSON 或 XML 的代码.即,如果我提供 XML,它应该返回 JSON,如果我提供 JSON,它应该提供 XML 输出.

I'm trying to write a code which can take either XML or JSON input and output JSON or XML respectively. I.e, if I give XML it should give back JSON, and if I give JSON it should give XML output.

有人告诉我,这可以使用 Jackson API 和 JAXB 注释来实现.谁能帮我解决这个问题?

I was told this is possible using Jackson API and JAXB Annotations. Can anyone help me out with this?

推荐答案

注意:我是EclipseLink JAXB (MOXy) 领导和 JAXB (JSR-222) 专家组.

Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.

以下是如何使用 MOXy 的 JSON 绑定来支持此用例的示例.

Below is an example of how you can use MOXy's JSON-binding to support this use case.

JAVA 模型

下面是一个使用 JAXB 元数据注释的示例域模型.相同的元数据将用于对象到 XML 和对象到 JSON 的转换.

Below is an example domain model annotated with JAXB metadata. The same metadata will be used for both the object-to-XML and object-to-JSON conversions.

客户

import java.util.List;
import javax.xml.bind.annotation.*;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {

    private int id;

    private String firstName;

    @XmlElement(nillable=true)
    private String lastName;

    private List<PhoneNumber> phoneNumbers;

}

电话号码

import javax.xml.bind.annotation.*;

@XmlAccessorType(XmlAccessType.FIELD)
public class PhoneNumber {

    @XmlAttribute
    private String type;

    @XmlValue
    private String number;

}

XML 输入

下面是我们将使用的 XML 输入.请注意 xsi:nil 属性如何在 lastName 元素上用于指示 null 值.另请注意 phoneNumbers 元素如何具有 type 属性.

Below is the XML input that we will use. Note how the xsi:nil attribute is used on the lastName element to indicate a null value. Also note how the phoneNumbers element has a type attribute.

<?xml version="1.0" encoding="UTF-8"?>
<customer>
   <id>123</id>
   <firstName>Jane</firstName>
   <lastName xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
   <phoneNumbers type="work">555-1111</phoneNumbers>
</customer>

演示代码

jaxb.properties

要将 MOXy 指定为您的 JAXB 提供程序,您需要在与域模型相同的包中包含一个名为 jaxb.properties 的文件,其中包含以下条目(请参阅:http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html):

To specify MOXy as your JAXB provider you need to include a file called jaxb.properties in the same package as your domain model with the following entry (see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html):

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

演示

以下演示代码会将 XML 转换为域模型,然后再转换回 JSON.

The following demo code will convert the XML to the domain model and then back to JSON.

import java.io.File;
import javax.xml.bind.*;
import org.eclipse.persistence.jaxb.MarshallerProperties;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Customer.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum14734741/input.xml");
        Customer customer = (Customer) unmarshaller.unmarshal(xml);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/json");
        marshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);
        marshaller.marshal(customer, System.out);
    }

}

JSON 输出

注意 lastName 键的 null 值如何表示为正确的 JSON.还要注意 type 键如何不包含任何与它对应的特殊指示符,它是 XML 表示中的 XML 属性.

Note how the null value for the lastName key is represented as proper JSON. Also note how the type key doesn't contain any special indicator corresponding to it being an XML attribute in the XML representation.

{
   "id" : 123,
   "firstName" : "Jane",
   "lastName" : null,
   "phoneNumbers" : [ {
      "type" : "work",
      "value" : "555-1111"
   } ]
}

相关文章