• 使用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

    相关依赖

            <dependency>
                <groupId>com.fasterxml.jackson.dataformatgroupId>
                <artifactId>jackson-dataformat-xmlartifactId>
            dependency>
    
            <dependency>
                <groupId>org.projectlombokgroupId>
                <artifactId>lombokartifactId>
            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 
         * @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>1001id>
        <name>testname>
        <node>
            <test1>test1test1>
            <test2>test2test2>
        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 = "1001testtest1test2";
    //        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);
    
    1001testtest2test1
    

    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 = "1001testzs18男ls19女";
            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 = "1001testzs18男ls19女";
            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>zsname>
                <age>18age>
                <sex>男sex>
             info>
             <info>
                <name>lsname>
                <age>19age>
                <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>zsname>
             <age>18age>
             <sex>男sex>
          info>
          <info>
             <name>lsname>
             <age>19age>
             <sex>女sex>
          info>
    root>
    

    所以在取值时代码:

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

    总结

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


  • 相关阅读:
    非技术人员也能快速实现Wordpress网页开发
    【Wio Terminal】使用WiFi(3)- Wi-F的高级使用
    oracle 还原被覆盖的视图
    【HiFlow】腾讯云场景连接器
    Prompt Engineering
    A-古代汉语复习重点
    lua --- 基本语法学习
    UMLChina为什么叒要翻译《分析模式》?
    3、Tomcat类加载机制
    【Spring Boot】日志文件
  • 原文地址:https://blog.csdn.net/weixin_46425661/article/details/142093313