Jackson 除了可以处理 JSON,还可以用来处理 XML(jackson-dataformat-xml 模块),可以轻松完成 Java 对象和 XML 文档的互转;本文主要介绍使用 Jackson 来处理 XML,文中所使用到的软件版本:Java 1.8.0_321、Jackson 2.13.3。
jackson-dataformat-xml 模拟 JAXB "代码优先" 的数据绑定方式,提供低级以及高级的方法来完成数据绑定工作。值得注意的是,jackson-dataformat-xml 的目标不是完整的 JAXB 克隆,或者成为一个通用的 XML 工具包。具体来说:
While XML serialization should ideally be similar to JAXB output, deviations are not automatically considered flaws (there are reasons for some differences)
What should be guaranteed is that any XML written using this module must be readable using module as well ("read what I wrote"): that is, we do aim for full round-trip support
From above: there are XML constructs that module will not be able to handle; including some cases JAXB (and other Java XML libraries) supports
This module also support constructs and use cases JAXB does not handle: specifically, rich type and object id support of Jackson are supported.
详情可参考官网文档:https://github.com/FasterXML/jackson-dataformat-xml.
2、Jackson 配置
处理 XML 的 XMLMapper 对象继承自处理 JSON 的 ObjectMapper 对象,因此他们的配置是类似的,具体可参考:
Java 操作 JSON 数据(4)--Jackson 操作 JSON 数据
。这里列出仅针对 XML 处理的注解:
@JacksonXmlRootElement
指定 XML 根标签的名字
@JacksonXmlProperty
属性或getter/setter方法上
指定属性对应 XML 映射的名称
序列化和反序列化时
@JacksonXmlText
属性或getter/setter方法上
将属性直接作为未被标签包裹的普通文本
序列化和反序列化时
@JacksonXmlCData
属性或getter/setter方法上
将属性值包裹在 CDATA 标签中
@JacksonXmlElementWrapper
属性或getter/setter方法上
类中有集合的属性时,是否生成包裹的标签
3、具体使用
3.1、引入依赖
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.13.3</version>
</dependency>
3.2、定义实体类
3.2.1、Grade
package com.abc.demo.xml;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import lombok.Data;
import lombok.ToString;
import java.util.List;
@Data
@ToString
@JacksonXmlRootElement(namespace = "http://www.w3.org/TR/html4/school/", localName = "school:grade")
public class Grade {
@JacksonXmlElementWrapper(useWrapping = false)
@JacksonXmlProperty(localName = "student", namespace = "http://www.w3.org/TR/html4/school/")
List<Student> students;
3.2.2、Student
package com.abc.demo.xml;
import com.fasterxml.jackson.dataformat.xml.annotation.*;
import lombok.Data;
import lombok.ToString;
@Data
@ToString
public class Student {
@JacksonXmlProperty(isAttribute = true)
private int rollno;
@JacksonXmlProperty(isAttribute = true)
private int age;
@JacksonXmlProperty(namespace = "http://www.w3.org/TR/html4/school/")
private String firstname;
private String lastname;
private String nickname;
private String marks;
public Student() {}
public Student(int rollno, int age, String firstname, String lastname, String nickname, String marks) {
this.rollno = rollno;
this.age = age;
this.firstname = firstname;
this.lastname = lastname;
this.nickname = nickname;
this.marks = marks;
3.3、定义待解析 XML(student.xml)
<?xml version="1.0" encoding="utf-8" ?>
<school:grade xmlns:school="http://www.w3.org/TR/html4/school/">
<school:student rollno="1" school:age="10">
<school:firstname>cxx1</school:firstname>
<lastname>Bob1</lastname>
<nickname>stars1</nickname>
<marks>85</marks>
</school:student>
<student rollno="2">
<firstname>cxx2</firstname>
<lastname>Bob2</lastname>
<nickname>stars2</nickname>
<marks>85</marks>
</student>
<student rollno="3">
<firstname>cxx3</firstname>
<lastname>Bob3</lastname>
<nickname>stars3</nickname>
<marks>85</marks>
</student>
</school:grade>
3.4、序列化及反序列化
package com.abc.demo.xml;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
public class JacksonCase {
private static final Logger logger = LoggerFactory.getLogger(JacksonCase.class);
* 序列化
@Test
public void serialize() throws IOException {
List<Student> students = new ArrayList<>();
Student student1 = new Student(1, 11,"cxx1", "Bob1", "stars1", "85");
Student student2 = new Student(2, 12, "cxx2", "Bob2", "stars2", "85");
Student student3 = new Student(3, 13, "cxx3", "Bob3", "stars3", "85");
students.add(student1);
students.add(student2);
students.add(student3);
Grade grade = new Grade();
grade.setStudents(students);
XmlMapper xmlMapper = new XmlMapper();
//美化输出
xmlMapper.enable(SerializationFeature.INDENT_OUTPUT);
logger.info(xmlMapper.writeValueAsString(grade));
* 反序列化
@Test
public void deserialize() throws IOException {
XmlMapper xmlMapper = new XmlMapper();
InputStream inputStream = JacksonCase.class.getResourceAsStream("student.xml");
//反序列化为实体对象
Grade grade = xmlMapper.readValue(inputStream, Grade.class);
logger.info(grade.toString());
inputStream = JacksonCase.class.getResourceAsStream("student.xml");
TypeReference<List<Student>> typeReference = new TypeReference<List<Student>>(){};
//反序列化为集合
List<Student> students = xmlMapper.readValue(inputStream, typeReference);
logger.info(students.toString());
inputStream = JacksonCase.class.getResourceAsStream("student.xml");
//使用树模型 API 解析 XML
JsonNode root = xmlMapper.readTree(inputStream);
JsonNode jsonNode = root.get("student").get(1);
logger.info("第一条数据,{}",jsonNode.toString());
logger.info("第一条数据,firstname={}", jsonNode.get("firstname").asText());
logger.info("第一条数据,marks={}", jsonNode.get("marks").asInt());