JavaBean 和 XML 相互转换(一)

下一篇文章:JavaBean 和 XML 相互转换(二)


在我们对接第三方系统时,经常会遇到第三方系统的报文采用 XML 格式,这是就需要将 JavaBean 和 XML 相互转换。

转换工具

在本示例中 JavaBean 和 XML 相互转换的工具采用 Hutool 提供的 JAXBUtil,所以在使用需要引入 Hutool 依赖,如下示例:


    cn.hutool
    hutool-all
    5.8.10

JAXBUtil 工具其实是对 javax.xml.bind.JAXBContext 进行了包装


下面通过一些简单示例,介绍 JavaBean 和 XML 相互转换常用到的一些注解,在正式开始介绍之前,先定义一些用于转换的 JavaBean,如下所示:

/**
 * 学校
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class School {

    /**
     * 学校名称
     */
    private String name;

    /**
     * 学校联系方式
     */
    private String phone;

    /**
     * 学校地址
     */
    private String address;

    /**
     * 班级
     */
    private List classes;
}
/**
 * 班级
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class ClassInfo {

    /**
     * 班级编号
     */
    private String classNo;

    /**
     * 班主任
     */
    private String teacher;

    /**
     * 学生
     */
    private List students;
}
/**
 * 学生
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class Student {

    /**
     * 学号
     */
    private String no;

    /**
     * 学生姓名
     */
    private String name;

    /**
     * 年龄
     */
    private Integer age;
  
    /**
     * 家庭地址
     */
    private String address;
}

@XmlRootElement

标注位置

是否必须

必须

注解作用

默认是将当前简单类名作为 XML 的 root 标签,如果设置该注解 name 属性,那么 name 属性值作为 root 标签

测试代码:只需关注只需结果 root 标签差异

public class XmlBeanMapperTest {

    /**
     * 测试 {@link XmlRootElement} 注解
     */
    @Test
    public void testXmlRootElement() {
        Student student = new Student("1001", "张三", 25, "北京市长安街 001 号");
        Console.log(JAXBUtil.beanToXml(student));
    }
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@XmlRootElement
public class Student {

   // 省略属性
}

执行结果:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

    北京市长安街 001 号
    25
    张三
    1001
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@XmlRootElement(name = "STUDENT")
public class Student {

    // 省略属性
}

执行结果:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

    北京市长安街 001 号
    25
    张三
    1001

@XmlType

标注位置

是否必须

非必须

注解作用

主要使用其 propOrder 属性,用于对 XML 元素排序,如果设置了 propOrder 属性,那么属性的值要包括所有的待转换的字段

@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@XmlRootElement
@XmlType(propOrder = {"no", "age", "name", "address"})
public class Student {

    // 省略属性
}

测试代码:

public class XmlBeanMapperTest {

    /**
     * 测试 {@link XmlType} 注解
     */
    @Test
    public void testXmlType() {
        Student student = new Student("1001", "张三", 25, "北京市长安街 001 号");
        Console.log(JAXBUtil.beanToXml(student));
    }
}

执行结果:

// 未添加 @XmlType 注解前
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

    北京市长安街 001 号
    25
    张三
    1001


// 添加后,按照指定的顺序排序
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

    1001
    25
    张三
    北京市长安街 001 号

@XmlAccessorType

标注位置

是否必须

非必须

注解作用

用于控制 JavaBean 和 XML 转换字段和元素之间的映射,包括如下四种控制类型:

  • PROPERTY:对 JavaBean 中有 Getter/Setter 方法或使用 @XmlElement 注解标注的属性进行映射
  • FIELD:对 JavaBean 中非 static、transient 修饰的属性进行映射
  • PUBLIC_MEMBER:默认值,对 JavaBean 中 public 修饰或有 Getter/Setter 方法或使用 @XmlElement 注解标注的属性进行映射
  • NONE:仅对 JavaBean 中使用 @XmlElement 注解标注的属性进行映射

注意:当使用 Lombok 中 @Data 注解时,若使用 PROPERTY 或 PUBLIC_MEMBER 类型时会出现异常,如果继续使用 @Data 那么就需要使用 FIELD 或 NONE 类型。

对上面公共的学生类做些修改,详见 Student 类中的注释:

//@Data  注释 Lombok @Data 注解,不自动生成 Getter/Setter 方法等
@ToString
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@XmlRootElement
@XmlAccessorType // 根据下面测试的场景,设置对应的值
public class Student {

    /**
     * 学号:有 Getter/Setter 方法(通过 Lombok @Getter/@Setter 注解,
     * 或手动编写 Getter/Setter 方法)
     */
    @Getter
    @Setter
    private String no;

    /**
     * 学生姓名:将原 private 修饰改为 public 修饰,也就是通过类实例就可以访问该变量
     */
    public String name;

    /**
     * 年龄:使用 @XmlElement 注解,现在可以先了解该注解是用于类属性和 XML 标签映射,
     * 后面详解
     */
    @XmlElement
    private Integer age;

    /**
     * 家庭地址:private 修饰的变量没有 Getter/Setter 方法
     */
    private String address;
}

测试类:

public class XmlBeanMapperTest {

    private static final String XML = "<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
" +
            "
" +
            "    北京市长安街 001 号
" +
            "    25
" +
            "    张三
" +
            "    1001
" +
            "";


    /**
     * 测试 {@link XmlAccessorType} 注解
     */
    @Test
    public void testXmlAccessorType() {
        Student student = new Student("1001", "张三", 25, "北京市长安街 001 号");
        Console.log(JAXBUtil.beanToXml(student));
        Console.log(JAXBUtil.xmlToBean(XML, Student.class));
    }
}

运行测试类,执行结果如下:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

    25
    1001


Student(no=1001, name=null, age=25, address=null)

可以看到当注解 @XmlAccessorType value=PROPERTY 时, JavaBean 和 XML 相互映射,只有有 Getter/Setter 方法或标注 @XmlElement 注解的属性生效。

运行测试类,执行结果如下:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

    1001
    张三
    25
    北京市长安街 001 号


Student(no=1001, name=张三, age=25, address=北京市长安街 001 号)

可以看到当注解 @XmlAccessorType value=FIELD 时, JavaBean 和 XML 相互映射,学生类中的字段都生效

运行测试类,执行结果如下:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

    张三
    25
    1001


Student(no=1001, name=张三, age=25, address=null)

可以看到当注解 @XmlAccessorType value=PUBLIC_MEMBER 时, JavaBean 和 XML 相互映射,只有有 Getter/Setter 方法或标注 @XmlElement 注解或 public 修饰的属性生效。

运行测试类,执行结果如下:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

    25


Student(no=null, name=null, age=25, address=null)

可以看到当注解 @XmlAccessorType value=NONE 时, JavaBean 和 XML 相互映射,只有有 @XmlElement 注解属性生效。



由于内容较多,其他内容详见下一篇文章,如果文章对大家有所帮助,欢迎点赞、关注、评论。

展开阅读全文

页面更新:2024-04-29

标签:长安街   北京市   注解   字段   班级   属性   类型   测试   方法   学生

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号

Top