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