当前位置: 首页 > article >正文

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

文章目录

  • Jackson Xml
    • 常用注解
    • 常用的配置属性
    • 相关依赖
    • jackson工具类
  • xml和对象相互转换
    • xml数据
    • 实体类
    • xml转为对象
    • 对象转为xml
  • xml和List相互转换
    • xml数据
    • 实体类
    • List转xml
    • xml转List
      • 方法1
      • 方法2
      • @JacksonXmlElementWrapper 的 useWrapping 参数区别
      • 总结


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

相关依赖

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

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

jackson工具类

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数据

<root>
    <id>1001</id>
    <name>test</name>
    <node>
        <test1>test1</test1>
        <test2>test2</test2>
    </node>
</root>

实体类

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;
}
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转为对象

    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);
    }

输出

XmlDataBo(id=1001, name=test, testBo=XmlDataTestBo(Test1=test1, Test2=test2))

对象转为xml

        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);
<root><id>1001</id><name>test</name><node><test2>test2</test2><test1>test1</test1></node></root>

xml和List相互转换

xml数据

<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 >

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 >

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 >

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

        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);

输出

<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

        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);

输出

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实体类

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;

}

测试

    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);
    }

输出

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 时,表示列表或数组被包裹在一个额外的元素中。例如以上代码中:
<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标签中。
所以在取值时代码:

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

所以在取值时代码:

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

总结

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



http://www.kler.cn/a/309005.html

相关文章:

  • 4.4 软件设计:UML顺序图
  • 前端-同源与跨域
  • 94个属于一区且接受医工交叉领域投稿的期刊汇总|个人观点·24-11-13
  • 冗余连接2 hard题 代随C#写法
  • 基于非时空的离身与反身智能
  • springboot项目中,使用ProGuard 对代码进行混淆
  • 碰撞检测 | 图解线段几何与线段相交检测原理(附ROS C++可视化)
  • pandas读取Excel保留空格与数字前置0
  • UNI-APP 富文本编辑器,可以对图片、文字格式进行编辑和混排。
  • python之openpyxl模块——实现Excel表格的处理(万字教学,全网最全,超详细!)
  • 深度解析代理IP地址与端口:定义及高效获取方法
  • 硬件工程师笔试面试——保险丝
  • 运维面试题1
  • 微信小程序中实现类似于 ECharts 的图表渲染及优化
  • Java项目实战II基于Java+Spring Boot+MySQL的作业管理系统设计与实现(源码+数据库+文档)
  • OpenAI o1——人工智能推理能力的飞跃,助力高级问题解决
  • Spark处理结构化数据:DataFrame、DataSet、SparkSQL
  • Linux5-echo,>,tail
  • 关于前后端跨域访问的问题
  • C语言16--宏定义和关键字
  • 【FFmpeg应用场景概述】
  • Nginx实用篇:实现负载均衡、限流与动静分离
  • source ~/.bash_profile有什么用
  • MySQL record 05 part
  • mysql5.7常用操作命令手册
  • 是时候对企业数字化转型进行一次复盘了