Skip to main content
 首页 » 编程设计

Jackson 生成xml格式文件

2022年07月19日147sky-heaven

Jackson 生成xml格式文件

Jackson是java应用中流行的操作Json工具库,很快成为Java生态中事实标准,Spring boot默认也使用Jackson。从版本2开始,支持json的同时引入成熟的xml实现。

1. 环境依赖

增加Jackson xml 模块,仅需要一个依赖:

<dependency> 
    <groupId>com.fasterxml.jackson.dataformat</groupId> 
    <artifactId>jackson-dataformat-xml</artifactId> 
    <version>2.9.0</version> 
</dependency> 

Gradle版本:

compile "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.9.0" 

1.1 配置Jackson Xml 模块

Jackson通常使用 ObjectMapper实例;如果要使用xml相关操作,则需要使用 XmlMapper类,其是 ObjectMapper类的派生类,两者使用方式几乎一致。

最简单方式定义:

ObjectMapper objectMapper = new XmlMapper(); 

也可以增加一些通用配置:

JacksonXmlModule xmlModule = new JacksonXmlModule(); 
xmlModule.setDefaultUseWrapper(false); 
ObjectMapper objectMapper = new XmlMapper(module); 

对2.9版本,仅对xml有效的配置包括:

  • setDefaultUseWrapper – 定义默认情况下是否为未带注释的列表属性使用包装器。即对列表属性生成一个外层元素。
  • setXMLTextElementName – 当处理字符串数据时使用虚拟名称。

1.2 Spring Boot配置

由于Spring Boot默认没有暴露XmlMapper作为Bean,因为会与 ObjectMapper冲突,XmlMapper是其子类。但可以使用MappingJackson2XmlHttpMessageConverter 信息转换Bean进行获取。配置示例:

@Component 
public class MetaConvert implements IMetaConvert{
    
    private ObjectMapper xmlMapper; 
    public MetaConvert(MappingJackson2XmlHttpMessageConverter xmlConverter) {
    
        xmlMapper = xmlConverter.getObjectMapper(); 
    } 
     
    @Override 
    public String convertMetaToXml(Object metaInfo) {
    
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 
 
        try {
    
            xmlMapper.writeValue(byteArrayOutputStream, metaInfo); 
        } catch (IOException e) {
    
            log.error(e.getMessage()); 
            throw MetaFileException.of(e.getMessage()); 
        } 
 
        return byteArrayOutputStream.toString(); 
    } 
 
} 
 

2. 处理xml

Jackson可以很轻松处理Json,利用一些注解进行标识。XmlMapperObjectMapper的子类,仅为了处理xml,这意味着Api完全相同,可以直接使用。

2.1 写Xml

写Xml使用Jackson提供的多个重载方法 writeValue()。举例,序列化对象至xml可以简单使用 writeValueAsString方法:

String xml = objectMapper.writeValueAsString(input); 

其他几个方法:

  • Writing to a String
  • Writing to a Byte Array
  • Writing to a java.io.OutputStream – 如:网络连接的流
  • Writing to a java.io.Writer
  • Writing to a java.io.File

2.2 读Xml

刚才我们看到Jackson可以很好地处理写操作,它也可以处理读操作,同样利用多个重载方法 readValue()方法。举例,从输入流中读xml生成Java Bean:

MyBean bean = objectMapper.readValue(inputStream, MyBean.class); 

其他重载方法有:

  • Reading from a String
  • Reading from a Byte Array
  • Reading from a java.io.InputStream – 如:网络连接的流
  • Reading from a java.io.Reader
  • Reading from a java.io.File

3. Jackson 序列化注解

Jackson XML模块支持Jackson提供的用于注释pojo的所有注释。这意味着我们有一组bean和注释,并根据ObjectMapper实例选择是获得XML还是JSON。在构造代码时,这是一个巨大的好处,因为不再担心在表示相同数据的不同bean之间进行转换,从而获得不同的序列化格式。

举例:

@JsonPropertyOrder({
   "age", "id", "name"}) 
public class Person {
    
    @JsonProperty("_id") 
    private String id; 
 
    private String name; 
 
    private int age; 
 
    @JsonIgnore 
    private String note; 
} 

生成json:

{
    
    "age":4, 
    "_id":"12345", 
    "name":"George" 
} 

xml格式:

<Person> 
    <age>4</age> 
    <_id>12345</_id> 
    <name>George</name> 
</Person> 

3.1 针对xml的注解

Jackson Xml 模块增加了对xml特性支持的属性。这些注解用于控制元素(包括根元素)的xml命名空间、本地名称,字段是否被渲染为元素或普通文本,元素内容是否被渲染为CData 包装,集合属性是否使用包装元素等。下面针对常用注解进行分别说明。

@JacksonXmlProperty

@JacksonXmlProperty可以用在bean的任何字段上,控制渲染元素的一些细节属性。通过该注解可以设置命名控件、本地名称、是否被序列化为元素或属性。举例如下:

public class Person {
    
    @JacksonXmlProperty( 
      isAttribute = true, namespace = "urn.stackify.jacksonxml", localName = "_id") 
    private String id; 
 
    @JacksonXmlProperty(namespace = "urn.stackify.jackson") 
    private String name; 
 
    private String note; 
} 

输出结果:

<Person xmlns:wstxns1="urn.stackify.jacksonxml" wstxns1:_id="12345"> 
    <wstxns2:name xmlns:wstxns2="urn.stackify.jackson">Graham</wstxns2:name> 
    <note>Hello</note> 
</Person> 

@JacksonXmlRootElement

@JacksonXmlRootElement与上面提及的注解类似,但作用与整个文档的根元素。可设定命名空间和本地名称,根元素不会作为属性序列化。我们看下面Person POJO示例:

@JacksonXmlRootElement(namespace = "urn.stackify.jacksonxml", localName = "PersonData") 
public class Person {
    
    private String id; 
 
    private String name; 
 
    private String note; 
} 

输出结果:

<PersonData xmlns="urn.stackify.jacksonxml"> 
    <id xmlns="">12345</id> 
    <name xmlns="">Graham</name> 
    <note xmlns="">Hello</note> 
</PersonData> 

@JacksonXmlText

我们在看看 @JacksonXmlText注解。其表示属性被渲染为普通文本,无需额外元素包裹。举例:

public class Person {
    
    private String id; 
 
    private String name; 
 
    @JacksonXmlText 
    private String note; 
} 

输出结果:

<Person> 
    <id>12345</id> 
    <name>Graham</name> 
    Hello 
</Person> 

当然你要谨慎使用该注解,确保生成xml为有效格式。

@JacksonXmlCData

@JacksonXmlCData注解表示其内容不被xml解析,一般和@JacksonXmlText一起使用。请看示例:

public class Person {
    
    private String id; 
 
    @JacksonXmlCData 
    private String name; 
 
    @JacksonXmlText 
    @JacksonXmlCData 
    private String note; 
} 

输出结果为:

<Person> 
    <id>12345</id> 
    <name><![CDATA[Graham]]></name> 
    <![CDATA[Hello]]> 
</Person> 

@JacksonXmlElementWrapper

@JacksonXmlElementWrapper 注解覆盖setDefaultUseWrapper的确省设置。其能够让集合属性决定是否使用包装元素,并且也可以控制包装元素的本地名称和命名空间。

使用包装元素则增加额外元素包括所有集合元素,反之,直接列出所有集合元素:

class Wrapper {
    
    @JacksonXmlElementWrapper(localName = "list") 
    private List names; 
} 

输出结果:

<Wrapper> 
    <list> 
        <names>John</names> 
        <names>Paul</names> 
        <names>George</names> 
        <names>Ringo</names> 
    </list> 
</Wrapper> 

如果设置不用包装元素:

@JacksonXmlElementWrapper(useWrapping = false) 

输出结果:

<Wrapper> 
    <names>John</names> 
    <names>Paul</names> 
    <names>George</names> 
    <names>Ringo</names> 
</Wrapper> 

4. 总结

Jackson可以灵活地采用相同方式处理JSON和XML数据,Jackson Xml 模块还增加xml特有的处理方式和注解。


本文参考链接:https://blog.csdn.net/neweastsun/article/details/108144382