本文针对使用JAXB实现JavaBean与XML之间的相互转换,基本涵盖所有场景。
JAXB是Java Architecture for XML Binding的缩写。可以将一个Java对象转变成为XML格式,反之亦然。
我们把对象与关系数据库之间的映射称为ORM,其实也可以把对象与XML之间的映射称为OXM(Object XML Mapping)。原来JAXB是Java EE的一部分,在JDK1.6中,SUN将其放到了Java SE中,这也是SUN的一贯做法。JDK1.6中自带的这个JAXB版本是2.0,比起1.0(JSR 31)来,JAXB2(JSR 222)用JDK5的新特性Annotation来标识要作绑定的类和属性等,这就极大简化了开发的工作量。
JAXBContext类:是应用的入口,用于管理XML/Java绑定信息。
Marshaller接口:将Java对象序列化为XML数据。
Unmarshaller接口:将XML数据反序列化为Java对象。
@XmlRootElement:将Java类或枚举类型映射到XML元素,用在Java类上,用于标注该类是xml的一个根节点。
@XmlElement:将Java类的一个属性映射到与属性同名的一个XML元素。通常与@XmlTransient搭配使用。
@XmlTransient:通常与 @XmlElement 须搭配使用的。@XmlElement用在属性上,用于指定生成xml的节点名,@XmlTransient用在对应的getter方法上,起到关联的作用。
@XmlElementWrapper :对于数组或集合(即包含多个元素的成员变量),生成一个包装该数组或集合的XML元素(称为包装器)。通常配合XmlElement一起使用,XmlElementWrapper指定数组名,XmlElement指定生成xml的节点名。
@XmlElementRef:用在类属性的getter方法上(即该属性是一个JavaBean),并且该属性是某些子类的父类,起到引用的作用。同时标注得有@XmlElementRef的类属性,其子类上需要使用@XmlRootElement标注,否则转换异常,提示找不到具体的引用实现。另外,转换时,需要将其子类的class一起传递到JAXBContext上下文中,否则也无法转换。
@XmlAccessorOrder:控制JAXB 绑定类中属性和字段的排序。
@XmlType:将Java类或枚举类型映射到XML模式类型
@XmlAccessorType(XmlAccessType.FIELD) :控制字段或属性的序列化。FIELD表示JAXB将自动绑定Java类中的每个非静态的(static)、非瞬态的(由@XmlTransient标 注)字段到XML。还有XmlAccessType.PROPERTY和XmlAccessType.NONE。
@XmlJavaTypeAdapter:使用定制的适配器(即扩展抽象类XmlAdapter并覆盖marshal()和unmarshal()方法),以序列化Java类为XML。
@XmlAttribute,将Java类的一个属性映射到与属性同名的一个XML属性。
- public class XmlBeanUtils {
-
- /**
- * Java Bean 转 Xml
- *
- * @param bean - Java Bean
- * @param inheritClazz - Java Bean中嵌套的类,且有继承关系的Java Class
- * @return - xml
- */
- public static String beanToXml(Object bean, Class>... inheritClazz) {
- try {
- JAXBContext context = initContext(bean.getClass(), inheritClazz);
- Marshaller marshaller = context.createMarshaller();
- // 格式化xml
- marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
- marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
- // 是否去掉xml头
- marshaller.setProperty(Marshaller.JAXB_FRAGMENT, false);
- StringWriter writer = new StringWriter();
- marshaller.marshal(bean, writer);
- return writer.toString();
- } catch (JAXBException e) {
- e.printStackTrace();
- }
- return null;
- }
-
- /**
- * Xml 转 Java Bean
- *
- * @param xml - xml
- * @param beanClazz - Java Bean Class
- * @param inheritClazz - Java Bean中嵌套的类,且有继承关系的Java Class
- * @return - bean
- */
- public static Object xmlToBean(String xml, Class> beanClazz, Class>... inheritClazz) {
- try {
- JAXBContext context = initContext(beanClazz, inheritClazz);
- Unmarshaller um = context.createUnmarshaller();
- StringReader sr = new StringReader(xml);
- return um.unmarshal(sr);
- } catch (JAXBException e) {
- e.printStackTrace();
- }
- return null;
- }
-
- /**
- * 初始化JAXBContext
- *
- * @param mainClazz - 序列化或反序列化Class
- * @param inheritClazz - Java Bean中嵌套的类,且有继承关系的Java Class
- * @return - JAXBContext
- */
- private static JAXBContext initContext(Class> mainClazz, Class>... inheritClazz) throws JAXBException {
- JAXBContext context;
- if (inheritClazz != null) {
- Class>[] clazzArr = new Class[inheritClazz.length + 1];
- clazzArr[0] = mainClazz;
- System.arraycopy(inheritClazz, 0, clazzArr, 1, clazzArr.length - 1);
- context = JAXBContext.newInstance(clazzArr);
- } else {
- context = JAXBContext.newInstance(mainClazz);
- }
- return context;
- }
-
- }
- import lombok.AllArgsConstructor;
- import lombok.NoArgsConstructor;
- import lombok.Setter;
- import lombok.ToString;
-
- import javax.xml.bind.annotation.XmlElement;
- import javax.xml.bind.annotation.XmlRootElement;
- import javax.xml.bind.annotation.XmlTransient;
-
- /**
- * 简单JavaBean与XML转换
- */
- public class SimpleTest {
- public static void main(String[] args) {
- Cat cat = new Cat("猫咪", "爱吃鱼");
- String xml = XmlBeanUtils.beanToXml(cat);
- System.out.println("bean->xml = " + xml);
- System.out.println("xml->bean = " + XmlBeanUtils.xmlToBean(xml, Cat.class));
- }
-
- @ToString
- @NoArgsConstructor
- @AllArgsConstructor
- @Setter
- @XmlRootElement(name = "Cat")
- static class Cat {
- @XmlElement(name = "CatName")
- private String name;
-
- @XmlElement(name = "Hobby")
- private String hobby;
-
- @XmlTransient
- public String getName() {
- return name;
- }
-
- @XmlTransient
- public String getHobby() {
- return hobby;
- }
- }
- }
-
-

- import lombok.AllArgsConstructor;
- import lombok.NoArgsConstructor;
- import lombok.Setter;
- import lombok.ToString;
-
- import javax.xml.bind.annotation.XmlElement;
- import javax.xml.bind.annotation.XmlRootElement;
- import javax.xml.bind.annotation.XmlTransient;
-
- /**
- * 继承关系JavaBean与XML转换
- */
- public class InheritBeanTest {
- public static void main(String[] args) {
- // 具有继承关系,使用Cat 或 Animal 接收都可以。
- // Cat cat = new Cat("猫咪", "爱吃鱼");
- Animal cat = new Cat("猫咪", "爱吃鱼");
- String xml = XmlBeanUtils.beanToXml(cat);
- System.out.println("bean->xml = " + xml);
- // 此处不能使用父类Animal来接收,因为无法推断具体的实现类是哪个,必须使用具体的实现类Cat来接收
- System.out.println("xml->bean = " + XmlBeanUtils.xmlToBean(xml, Cat.class));
- }
-
- @Setter
- abstract static class Animal {
- // 不建议定义属性,因为从XML->Bean时,父类属性会丢失
- }
-
- @ToString
- @NoArgsConstructor
- @AllArgsConstructor
- @Setter
- @XmlRootElement(name = "Cat")
- static class Cat extends Animal {
- @XmlElement(name = "CatName")
- private String name;
-
- @XmlElement(name = "Hobby")
- private String hobby;
-
- @XmlTransient
- public String getName() {
- return name;
- }
-
- @XmlTransient
- public String getHobby() {
- return hobby;
- }
- }
- }

- import lombok.AllArgsConstructor;
- import lombok.NoArgsConstructor;
- import lombok.Setter;
- import lombok.ToString;
-
- import javax.xml.bind.annotation.XmlElement;
- import javax.xml.bind.annotation.XmlRootElement;
- import javax.xml.bind.annotation.XmlTransient;
-
- /**
- * 有嵌套关系的JavaBean与XML转换
- */
- public class NestBeanTest {
- public static void main(String[] args) {
- Cat cat = new Cat("猫咪", "爱吃鱼");
- Person person = new Person("貂蝉", 18, cat);
- String xml = XmlBeanUtils.beanToXml(person);
- System.out.println("bean->xml = " + xml);
- System.out.println("xml->bean = " + XmlBeanUtils.xmlToBean(xml, Person.class));
- }
-
- @ToString
- @NoArgsConstructor
- @AllArgsConstructor
- @Setter
- @XmlRootElement(name = "Person")
- static class Person {
- @XmlElement(name = "UserName")
- private String name;
-
- @XmlElement(name = "Age")
- private int age;
-
- // 嵌套的JavaBean
- @XmlElement(name = "Pet")
- private Cat cat;
-
- @XmlTransient
- public String getName() {
- return name;
- }
-
- @XmlTransient
- public int getAge() {
- return age;
- }
-
- @XmlTransient
- public Cat getCat() {
- return cat;
- }
- }
-
-
- @ToString
- @NoArgsConstructor
- @AllArgsConstructor
- @Setter
- @XmlRootElement(name = "Cat")
- static class Cat {
- @XmlElement(name = "CatName")
- private String name;
-
- @XmlElement(name = "Hobby")
- private String hobby;
-
- @XmlTransient
- public String getName() {
- return name;
- }
-
- @XmlTransient
- public String getHobby() {
- return hobby;
- }
- }
- }
-
-
1.4.嵌套类属性是的集合(数组)普通对象的转换- import lombok.AllArgsConstructor;
- import lombok.NoArgsConstructor;
- import lombok.Setter;
- import lombok.ToString;
-
- import javax.xml.bind.annotation.XmlElement;
- import javax.xml.bind.annotation.XmlElementWrapper;
- import javax.xml.bind.annotation.XmlRootElement;
- import javax.xml.bind.annotation.XmlTransient;
- import java.util.ArrayList;
- import java.util.List;
-
- /**
- * 有嵌套关系的集合JavaBean与XML转换
- */
- public class NestListBeanTest {
- public static void main(String[] args) {
- List
cats = new ArrayList<>(); - cats.add(new Cat("大猫咪", "爱吃大鱼"));
- cats.add(new Cat("小猫咪", "爱吃小鱼"));
- Person person = new Person("貂蝉", 18, cats);
- String xml = XmlBeanUtils.beanToXml(person);
- System.out.println("bean->xml = " + xml);
- System.out.println("xml->bean = " + XmlBeanUtils.xmlToBean(xml, Person.class));
- }
-
- @ToString
- @NoArgsConstructor
- @AllArgsConstructor
- @Setter
- @XmlRootElement(name = "Person")
- static class Person {
- @XmlElement(name = "UserName")
- private String name;
-
- @XmlElement(name = "Age")
- private int age;
-
- // 嵌套的集合JavaBean:XmlElementWrapper指定集合数组XML节点名,XmlElement指定具体的节点名
- @XmlElementWrapper(name = "PetArray")
- @XmlElement(name = "Pet")
- private List
cats; -
- @XmlTransient
- public String getName() {
- return name;
- }
-
- @XmlTransient
- public int getAge() {
- return age;
- }
-
- @XmlTransient
- public List
getCats() { - return cats;
- }
- }
-
-
- @ToString
- @NoArgsConstructor
- @AllArgsConstructor
- @Setter
- @XmlRootElement(name = "Cat")
- static class Cat {
- @XmlElement(name = "CatName")
- private String name;
-
- @XmlElement(name = "Hobby")
- private String hobby;
-
- @XmlTransient
- public String getName() {
- return name;
- }
-
- @XmlTransient
- public String getHobby() {
- return hobby;
- }
- }
- }
-
-
1.5.嵌套的类属性是继承关系对象的转换- import lombok.AllArgsConstructor;
- import lombok.NoArgsConstructor;
- import lombok.Setter;
- import lombok.ToString;
-
- import javax.xml.bind.annotation.XmlElement;
- import javax.xml.bind.annotation.XmlElementRef;
- import javax.xml.bind.annotation.XmlRootElement;
- import javax.xml.bind.annotation.XmlTransient;
-
- /**
- * 有嵌套且有继承关系的JavaBean与XML转换
- */
- public class NestInheritBeanTest {
- public static void main(String[] args) {
- // 此处使用Animal或Cat来接收都是可以的,因为已经创建了具体的Bean
- Animal cat = new Cat("猫咪", "爱吃鱼");
- Person person = new Person("貂蝉", 18, cat);
- // 转换时需要将Person中Animal类属性的实现类Cat.class传入。否则无法无法转换,因为不清楚具体的实现。
- String xml = XmlBeanUtils.beanToXml(person, Cat.class);
- System.out.println("bean->xml = " + xml);
- // 转换时需要将Person中Animal类属性的实现类Cat.class传入。否则无法无法转换,因为不清楚具体的实现。
- System.out.println("xml->bean = " + XmlBeanUtils.xmlToBean(xml, Person.class, Cat.class));
- }
-
- @ToString
- @NoArgsConstructor
- @AllArgsConstructor
- @Setter
- @XmlRootElement(name = "Person")
- static class Person {
- @XmlElement(name = "UserName")
- private String name;
-
- @XmlElement(name = "Age")
- private int age;
-
- // 嵌套的JavaBean,且是父类,此处不能使用@XmlElement标注,否则会报错,
- // 原因是父类不知道具体的子类实现,需要在子类中使用@XmlRootElement标注具体的实现
- private Animal animal;
-
- @XmlTransient
- public String getName() {
- return name;
- }
-
- @XmlTransient
- public int getAge() {
- return age;
- }
-
- // 必须使用@XmlElementRef来标注父类,起到引用的作用
- @XmlElementRef
- public Animal getAnimal() {
- return animal;
- }
- }
-
-
- @Setter
- abstract static class Animal {
- }
-
- @ToString
- @NoArgsConstructor
- @AllArgsConstructor
- @Setter
- @XmlRootElement(name = "Cat")
- static class Cat extends Animal {
- @XmlElement(name = "CatName")
- private String name;
-
- @XmlElement(name = "Hobby")
- private String hobby;
-
- @XmlTransient
- public String getName() {
- return name;
- }
-
- @XmlTransient
- public String getHobby() {
- return hobby;
- }
- }
- }
-
-
- import lombok.AllArgsConstructor;
- import lombok.NoArgsConstructor;
- import lombok.Setter;
- import lombok.ToString;
-
- import javax.xml.bind.annotation.*;
- import java.util.ArrayList;
- import java.util.List;
-
- /**
- * 有嵌套且有继承关系的集合JavaBean与XML转换
- */
- public class NestInheritListBeanTest {
- public static void main(String[] args) {
- // 此处使用Animal来接,属于List泛型知识,此处不再赘述
- List
animals = new ArrayList<>(); - animals.add(new Cat("大猫咪", "爱吃大鱼"));
- animals.add(new Cat("小猫咪", "爱吃小鱼"));
- Person person = new Person("貂蝉", 18, animals);
- // 转换时需要将Person中Animal类属性的实现类Cat.class传入。否则无法无法转换,因为不清楚具体的实现。
- String xml = XmlBeanUtils.beanToXml(person, Cat.class);
- System.out.println("bean->xml = " + xml);
- // 转换时需要将Person中Animal类属性的实现类Cat.class传入。否则无法无法转换,因为不清楚具体的实现。
- System.out.println("xml->bean = " + XmlBeanUtils.xmlToBean(xml, Person.class, Cat.class));
- }
-
- @ToString
- @NoArgsConstructor
- @AllArgsConstructor
- @Setter
- @XmlRootElement(name = "Person")
- static class Person {
- @XmlElement(name = "UserName")
- private String name;
-
- @XmlElement(name = "Age")
- private int age;
-
- // 嵌套的JavaBean,且是父类,此处不能使用@XmlElement标注,否则会报错,
- // 原因是父类不知道具体的子类实现,需要在子类中使用@XmlRootElement标注具体的实现
- private List
animals; -
- @XmlTransient
- public String getName() {
- return name;
- }
-
- @XmlTransient
- public int getAge() {
- return age;
- }
-
- // 必须使用@XmlElementRef来标注父类,起到引用的作用
- // 必须使用@XmlElementWrapper指定集合数组XML节点名
- @XmlElementRef
- @XmlElementWrapper(name = "PetArray")
- public List
getAnimals() { - return animals;
- }
- }
-
- @Setter
- abstract static class Animal {
- }
-
- @ToString
- @NoArgsConstructor
- @AllArgsConstructor
- @Setter
- @XmlRootElement(name = "Cat")
- static class Cat extends Animal {
- @XmlElement(name = "CatName")
- private String name;
-
- @XmlElement(name = "Hobby")
- private String hobby;
-
- @XmlTransient
- public String getName() {
- return name;
- }
-
- @XmlTransient
- public String getHobby() {
- return hobby;
- }
- }
- }
1.7.有继承关系且父类有属性的对象的转换(不推荐使用,XML->Bean转换时父类属性会丢失)
- import lombok.AllArgsConstructor;
- import lombok.NoArgsConstructor;
- import lombok.Setter;
- import lombok.ToString;
-
- import javax.xml.bind.annotation.XmlElement;
- import javax.xml.bind.annotation.XmlElementRef;
- import javax.xml.bind.annotation.XmlRootElement;
- import javax.xml.bind.annotation.XmlTransient;
-
- /**
- * 有嵌套且有继承关系的JavaBean与XML转换
- * 且父类中定义了属性,XML->Bean,父类属性会丢失(除非必要,不要再父类中定义属性)
- */
- public class NoSupportNestInheritBeanTest {
- public static void main(String[] args) {
- // 此处使用Animal或Cat来接收都是可以的,因为已经创建了具体的Bean
- Cat cat = new Cat("猫咪", "爱吃鱼");
- cat.setCountry("中国");
- Person person = new Person("貂蝉", 18, cat);
- // 转换时需要将Person中Animal类属性的实现类Cat.class传入。否则无法无法转换,因为不清楚具体的实现。
- String xml = XmlBeanUtils.beanToXml(person, Cat.class);
- System.out.println("bean->xml = " + xml);
- // 转换时需要将Person中Animal类属性的实现类Cat.class传入。否则无法无法转换,因为不清楚具体的实现。
- System.out.println("xml->bean = " + XmlBeanUtils.xmlToBean(xml, Person.class, Cat.class));
- }
-
- @ToString
- @NoArgsConstructor
- @AllArgsConstructor
- @Setter
- @XmlRootElement(name = "Person")
- static class Person {
- @XmlElement(name = "UserName")
- private String name;
-
- @XmlElement(name = "Age")
- private int age;
-
- // 嵌套的JavaBean,且是父类,此处不能使用@XmlElement标注,否则会报错,
- // 原因是父类不知道具体的子类实现,需要在子类中使用@XmlRootElement标注具体的实现
- private Animal animal;
-
- @XmlTransient
- public String getName() {
- return name;
- }
-
- @XmlTransient
- public int getAge() {
- return age;
- }
-
- // 必须使用@XmlElementRef来标注父类,起到引用的作用
- @XmlElementRef
- public Animal getAnimal() {
- return animal;
- }
- }
-
-
- @Setter
- abstract static class Animal {
- @XmlElement(name = "Country")
- private String country;
-
- @XmlTransient
- public String getCountry() {
- return country;
- }
- }
-
- @ToString
- @NoArgsConstructor
- @AllArgsConstructor
- @Setter
- @XmlRootElement(name = "Cat")
- static class Cat extends Animal {
- @XmlElement(name = "CatName")
- private String name;
-
- @XmlElement(name = "Hobby")
- private String hobby;
-
- @XmlTransient
- public String getName() {
- return name;
- }
-
- @XmlTransient
- public String getHobby() {
- return hobby;
- }
- }
- }