使用jackson将xml和对象、List相互转换

文章目录


Jackson Xml

Jackson 是一个广泛使用的 JSON 处理库,但在处理 XML 数据时,Jackson 也提供了相应的支持。虽然 Jackson 的主要用途是处理 JSON 数据,但通过在pom.xml中引入jackson-dataformat-xml 模块,可以很方便地将 Java 对象序列化为 XML 文档或将 XML 文档反序列化为 Java 对象。

常用注解

  • @JacksonXmlRootElement:定义Xml根元素,默认使用类的SimpleName
  • @JacksonXmlProperty:指定属性名称,以及属性是否被写成一个XML元素或属性
  • @JacksonXmlElementWrapper:允许指定用于包装List和Map属性的XML元素。类似JAXB的@XmlElementWrapper
  • @JacksonXmlCData:允许指定一个属性的值被序列化在一个CData标签中

常用的配置属性

  • SerializationFeature.INDENT_OUTPUT:是否格式化输出,默认false
  • SerializationFeature.WRITE_DATES_AS_TIMESTAMPS:日期写为时间戳,默认true
  • MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES:反序列化忽略大小写,默认false
  • DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES:反序列化时,未知字段是否直接失败,默认true

相关依赖

xml 复制代码
        <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-xml</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

jackson工具类

java 复制代码
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;

import java.io.IOException;

/**
 * @author qf
 * @since 2024/09/11 19:04
 */
public class JacksonXmlUtil {
    private static class SingletonHolder {
        private static XmlMapper xmlMapper = new XmlMapper();
        static {
            // 在构造器中进行配置
            //反序列化的时候如果多了其他属性,不抛出异常
            xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        }
    }

    public static XmlMapper getXmlSingleton() {
        XmlMapper mapper = SingletonHolder.xmlMapper;
        return mapper;
    }

    /**
     * 对象转xml
     *
     * @param obj
     * @return
     * @throws JsonProcessingException
     */
    public static String toXml(Object obj) throws JsonProcessingException {
        ObjectMapper mapper = getXmlSingleton();
        return mapper.writeValueAsString(obj);
    }


    /**
     * xml转为对象
     *
     * @param xml
     * @param clazz
     * @param <T>
     * @return
     * @throws IOException
     */
    public static <T> T toXmlObject(String xml, Class<T> clazz) throws IOException {
        XmlMapper mapper = getXmlSingleton();
        return mapper.readValue(xml, clazz);
    }
}

xml和对象相互转换

xml数据

xml 复制代码
<root>
    <id>1001</id>
    <name>test</name>
    <node>
        <test1>test1</test1>
        <test2>test2</test2>
    </node>
</root>

实体类

java 复制代码
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import lombok.Data;

import java.util.List;

/**
 * @author qf
 * @since 2024/09/11 19:06
 */
@Data
@JacksonXmlRootElement(localName = "root")
public class XmlDataBo {

    @JacksonXmlProperty(localName = "id")
    private Long id;

    @JacksonXmlProperty(localName = "name")
    private String name;

    @JacksonXmlProperty(localName = "node")
    private XmlDataTestBo testBo;
}
java 复制代码
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import lombok.Data;

/**
 * @author qf
 * @since 2024/09/10 19:42
 */
@Data
@JacksonXmlRootElement(localName = "node")
public class XmlDataTestBo {
    @JacksonXmlProperty(localName = "test1")
    private String Test1;
    @JacksonXmlProperty(localName = "test2")
    private String Test2;
}

xml转为对象

java 复制代码
    public static void main(String[] args) throws IOException {
        String xmlStr = "<root><id>1001</id><name>test</name><node><test1>test1</test1><test2>test2</test2></node></root>";
//        XmlDataBo xmlBo = JacksonXmlUtil.toXmlObject(xmlStr, XmlDataBo.class);
        XmlMapper xmlMapper = new XmlMapper();
        xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        XmlDataBo xmlBo = xmlMapper.readValue(xmlStr, XmlDataBo.class);
    }

输出

txt 复制代码
XmlDataBo(id=1001, name=test, testBo=XmlDataTestBo(Test1=test1, Test2=test2))

对象转为xml

java 复制代码
        XmlDataTestBo testBo = new XmlDataTestBo();
        testBo.setTest1("test1");
        testBo.setTest2("test2");
        XmlDataBo xmlDataBo = new XmlDataBo();
        xmlDataBo.setId(1001L);
        xmlDataBo.setName("test");
        xmlDataBo.setTestBo(testBo);
        String xml = JacksonXmlUtil.toXml(xmlDataBo);
        System.out.println(xml);
txt 复制代码
<root><id>1001</id><name>test</name><node><test2>test2</test2><test1>test1</test1></node></root>

xml和List相互转换

xml数据

java 复制代码
<root>
    <id>1001</id>
    <name>test</name>
    <node>
        <info>
            <name>zs</name>
            <age>18</age>
            <sex>男</sex>
         </info>
         <info>
            <name>ls</name>
            <age>19</age>
            <sex>女</sex>
         </info>
    </node>
</root>

实体类

根标签 < root >

java 复制代码
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import lombok.Data;

/**
 * @author qbh
 * @since 2024/09/10 19:25
 */
@Data
@JacksonXmlRootElement(localName = "root")
public class XmlDataBo {

    @JacksonXmlProperty(localName = "id")
    private Long id;

    @JacksonXmlProperty(localName = "name")
    private String name;

    @JacksonXmlProperty(localName = "node")
    private XmlDataTestBo testBo;

}

node标签< node >

java 复制代码
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 java.util.List;

/**
 * @author qf
 * @since 2024/09/10 18:42
 */
@Data
@JacksonXmlRootElement(localName = "node")
public class XmlDataTestBo {
//    @JacksonXmlProperty(localName = "test1")
//    private String Test1;
//    @JacksonXmlProperty(localName = "test2")
//    private String Test2;

    /**
     * JacksonXmlElementWrapper注解用于指定列表或数组属性在XML中的包装元素,以提供更好的结构化层次和语义意义。
     *  当useWrapping = true:列表或数组会被包裹在一个额外的元素中。
     *  当useWrapping = false:列表或数组不会被包裹在额外的元素中。
     */
    @JacksonXmlElementWrapper(useWrapping = false)
    @JacksonXmlProperty(localName = "info")
    private List<XmlDataInfoBo> infoBos;
}

info标签 < info >

java 复制代码
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.lang.ref.PhantomReference;

/**
 * @author qf
 * @since 2024/09/10 19:27
 */
@NoArgsConstructor
@AllArgsConstructor
@Data
@JacksonXmlRootElement(localName = "info")
public class XmlDataInfoBo {

    @JacksonXmlProperty(localName = "name")
    private String name;

    @JacksonXmlProperty(localName = "age")
    private Integer age;

    @JacksonXmlProperty(localName = "sex")
    private String sex;
}

List转xml

java 复制代码
        XmlDataBo xmlDataBo = new XmlDataBo();
        xmlDataBo.setId(1001L);
        xmlDataBo.setName("test");
        List<XmlDataInfoBo> infoBos = new ArrayList<>();
        infoBos.add(new XmlDataInfoBo("zs", 18, "男"));
        infoBos.add(new XmlDataInfoBo("ls", 19, "女"));
        XmlDataTestBo testBo = new XmlDataTestBo();
        testBo.setInfoBos(infoBos);
        xmlDataBo.setTestBo(testBo);
        String xml = JacksonXmlUtil.toXml(xmlDataBo);
        System.out.println(xml);

输出

java 复制代码
<root><id>1001</id><name>test</name><node><info><name>zs</name><age>18</age><sex>男</sex></info><info><name>ls</name><age>19</age><sex>女</sex></info></node></root>

xml转List

方法1

java 复制代码
        String xmlStr = "<root><id>1001</id><name>test</name><node><info><name>zs</name><age>18</age><sex>男</sex></info><info><name>ls</name><age>19</age><sex>女</sex></info></node></root>";
        XmlDataBo xmlDataBo = JacksonXmlUtil.toXmlObject(xmlStr, XmlDataBo.class);
        System.out.println(xmlDataBo);

输出

txt 复制代码
XmlDataBo(id=1001, name=test, testBo=XmlDataTestBo(infoBos=[XmlDataInfoBo(name=zs, age=18, sex=男), XmlDataInfoBo(name=ls, age=19, sex=女)]))

方法2

也可以直接从node标签中拿取列表(跳过node标签直接拿列表info)

修改root实体类

java 复制代码
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 java.util.List;

/**
 * @author qbh
 * @since 2024/09/10 17:25
 */
@Data
@JacksonXmlRootElement(localName = "root")
public class XmlDataBo {

    @JacksonXmlProperty(localName = "id")
    private Long id;

    @JacksonXmlProperty(localName = "name")
    private String name;

//    @JacksonXmlProperty(localName = "node")
//    private XmlDataTestBo testBo;

    @JacksonXmlElementWrapper(useWrapping = true )
    @JacksonXmlProperty(localName = "node")
    private List<XmlDataInfoBo> infoBos;

}

测试

java 复制代码
    public static void main(String[] args) throws IOException {
        String xmlStr = "<root><id>1001</id><name>test</name><node><info><name>zs</name><age>18</age><sex>男</sex></info><info><name>ls</name><age>19</age><sex>女</sex></info></node></root>";
        XmlDataBo xmlDataBo = JacksonXmlUtil.toXmlObject(xmlStr, XmlDataBo.class);
        System.out.println(xmlDataBo);
    }

输出

txt 复制代码
XmlDataBo(id=1001, name=test, infoBos=[XmlDataInfoBo(name=zs, age=18, sex=男), XmlDataInfoBo(name=ls, age=19, sex=女)])

@JacksonXmlElementWrapper 的 useWrapping 参数区别

@JacksonXmlElementWrapper 注解用于指定列表或数组属性在 XML 中的包装元素。useWrapping 参数控制是否使用额外的包装元素来包裹列表或数组。

  1. useWrapping = true (默认)
    当 useWrapping = true 时,表示列表或数组被包裹在一个额外的元素中。例如以上代码中:
xml 复制代码
<root>
    <node>
        <info>
            <name>zs</name>
            <age>18</age>
            <sex>男</sex>
         </info>
         <info>
            <name>ls</name>
            <age>19</age>
            <sex>女</sex>
         </info>
    </node>
</root>

在这个例子中,info标签被包裹在node标签中。

所以在取值时代码:

java 复制代码
    @JacksonXmlElementWrapper(useWrapping = true )
    @JacksonXmlProperty(localName = "node")
    private List<XmlDataInfoBo> infoBos;
  1. useWrapping = false
    当 useWrapping = false 时,表示列表或数组没有被包裹在额外的元素中。例如以上代码中:
xml 复制代码
<root>
     <info>
         <name>zs</name>
         <age>18</age>
         <sex>男</sex>
      </info>
      <info>
         <name>ls</name>
         <age>19</age>
         <sex>女</sex>
      </info>
</root>

所以在取值时代码:

java 复制代码
    @JacksonXmlElementWrapper(useWrapping = false)
    @JacksonXmlProperty(localName = "info")
    private List<XmlDataInfoBo> infoBos;

总结

当列表或数组会被包裹在一个额外的元素中或想直接从父标签拿子标签列表时,选择useWrapping = true。

列表或数组没有被包裹在额外的元素中时,选择useWrapping = false。


相关推荐
白总Server6 分钟前
MySQL在大数据场景应用
大数据·开发语言·数据库·后端·mysql·golang·php
luoluoal15 分钟前
java项目之企业级工位管理系统源码(springboot)
java·开发语言·spring boot
ch_s_t17 分钟前
新峰商城之购物车(一)
java·开发语言
蜜桃小阿雯22 分钟前
JAVA开源项目 校园美食分享平台 计算机毕业设计
java·jvm·spring boot·spring cloud·intellij-idea·美食
黄昏_25 分钟前
苍穹外卖Day01-2
java·spring
努力的八爪鱼37 分钟前
记录工作中遇到的问题(持续更新~)
java
求学小火龙39 分钟前
ElasticSearch介绍+使用
java·大数据·elasticsearch
mikey棒棒棒40 分钟前
算法练习题25——合并多项式
java·算法·hashmap·哈希·多项式
kimloner42 分钟前
工厂模式(二):工厂方法模式
java·设计模式·工厂方法模式
月临水1 小时前
JavaEE:网络编程(UDP)
java·网络·udp·java-ee