当java对象的某个属性使用泛型时,普通对象都没问题,但是遇到HashSet这种集合类封装的元素时,就会出现元素内容序列化不出来的问题,详见如下:
一、示例:
第一步:定义java对象
package step3; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement @XmlAccessorType(value = XmlAccessType.PROPERTY) public class Customer<T> { String name; int age; int id; T t; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public int getId() { return id; } public void setId(int id) { this.id = id; } @Override public String toString() { return "Customer [id=" + id + ",name=" + name + ",age=" + age + ",t=" + t + "]"; } public T getT() { return t; } public void setT(T t) { this.t = t; } }
package step3; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; @XmlAccessorType(value = XmlAccessType.PROPERTY) public class Book { private String id; private String name; private float price; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public float getPrice() { return price; } public void setPrice(float price) { this.price = price; } @Override public String toString() { return "Book [id=" + id + ",name=" + name + ",price=" + price + "]"; } }
第二步:编组(JAXBContext.newInstance(Customer.class,HashSet.class);方法添加了
HashSet的class对象,以提供给JAXBContext使用。)
package step3; import java.io.File; import java.util.HashSet; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; //Marshaller public class Object2XmlDemo { public static void main(String[] args) { Customer<HashSet<Book>> customer = new Customer<HashSet<Book>>(); customer.setId(100); customer.setName("suo"); customer.setAge(29); Book book = new Book(); book.setId("1"); book.setName("哈里波特"); book.setPrice(100); Book book2 = new Book(); book2.setId("2"); book2.setName("苹果"); book2.setPrice(50); HashSet<Book> bookSet = new HashSet<Book>(); bookSet.add(book); bookSet.add(book2); customer.setT(bookSet); try { File file = new File("C:\\file1.xml"); JAXBContext jaxbContext = JAXBContext.newInstance(Customer.class, HashSet.class); Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); // output pretty printed jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); jaxbMarshaller.marshal(customer, file); jaxbMarshaller.marshal(customer, System.out); } catch (JAXBException e) { e.printStackTrace(); } } }
得到的xml:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <customer> <age>29</age> <id>100</id> <name>suo</name> <t xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="hashSet"/> </customer>
注:
1.泛型使用集合元素替代时,泛型属性所对应的xml没有序列化出来。
2.若JAXBContext.newInstance(Customer.class,HashSet.class);不添加HashSet
的class对象,则报错:
[javax.xml.bind.JAXBException: class java.util.HashSet nor any of its super class is known to this context.]
解决办法:
第一步:新增HashSet的包装类
Book类和Customer类相关代码均不需要改变,新增一个HashSet的包装类,定义如下:
package step4; import java.util.HashSet; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; public class BookSet { private HashSet<Book> bookSet = new HashSet<Book>(); //仅包含get方法,未包含set方法 @XmlElementWrapper(name = "bookSet")//该注解非必须,仅是标注集合元素 @XmlElement(name="book") public HashSet<Book> getBookSet() { return bookSet; } public void addBook(Book book){ bookSet.add(book); } }
注:
1.BookSet类内部使用HashSet实现.
2.BookSet类在get方法上添加了@XmlElementWrapper(name = "bookSet")注解。
第二步:编组
package step4; import java.io.File; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; //Marshaller public class Object2XmlDemo { public static void main(String[] args) { Customer<BookSet> customer = new Customer<BookSet>(); customer.setId(100); customer.setName("suo"); customer.setAge(29); Book book = new Book(); book.setId("1"); book.setName("哈里波特"); book.setPrice(100); Book book2 = new Book(); book2.setId("2"); book2.setName("苹果"); book2.setPrice(50); BookSet bookSet = new BookSet(); bookSet.addBook(book); bookSet.addBook(book2); customer.setT(bookSet); try { File file = new File("C:\\file1.xml"); JAXBContext jaxbContext = JAXBContext.newInstance(Customer.class, BookSet.class); Marshaller jaxbMarshaller = jaxbContext.createMarshaller(); // output pretty printed jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); jaxbMarshaller.marshal(customer, file); jaxbMarshaller.marshal(customer, System.out); } catch (JAXBException e) { e.printStackTrace(); } } }
注:
1.定义Customer对象时,使用包装类,即:
Customer<BookSet> customer = new Customer<BookSet>();
2.JAXBContext调用newInstance()方法时,传入BookSet的class对象,告知BookSet的类型,即:JAXBContext.newInstance(Customer.class,BookSet.class);
得到的xml:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <customer> <age>29</age> <id>100</id> <name>suo</name> <t xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="bookSet"> <bookSet> <book> <id>2</id> <name>苹果</name> <price>50.0</price> </book> <book> <id>1</id> <name>哈里波特</name> <price>100.0</price> </book> </bookSet> </t> </customer>