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,利用一些注解进行标识。XmlMapper
是 ObjectMapper
的子类,仅为了处理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