本篇主要讲解XStream的Converter
- 简单的Converter
先创建一个简单的pojo类
public class Person {
@Override
public String toString() {
// TODO Auto-generated method stub
return getName();
}
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
创建一个Person的Converter
public class PersonConverter implements Converter {
@Override
public void marshal(Object value, HierarchicalStreamWriter writer,
MarshallingContext content) {
Person person=(Person)value;
writer.startNode("fullname");
writer.setValue(person.getName());
writer.endNode();
}
@Override
public Object unmarshal(HierarchicalStreamReader reader,
UnmarshallingContext content) {
Person person=new Person();
reader.moveDown();
person.setName(reader.getValue());
reader.moveUp();
return person;
}
@Override
public boolean canConvert(Class calzz) {
return Person.class==calzz;
}
}
测试Person的Converter
public class PersonTest {
/**
* @param args
*/
public static void main(String[] args) {
Person person=new Person();
person.setName("张三");
XStream stream=new XStream();
stream.alias("person", Person.class);
//stream.registerConverter(new PersonConverter());
stream.registerConverter(new PersonSingleValueConverter());
String xml=stream.toXML(person);
System.out.println("xml:"+xml);
Person p=(Person) stream.fromXML(xml);
String name=p.getName();
System.out.println("name:"+name);
}
}
如果一个只有一个String类型的属性,我们可以用AbstractSingleValueConverter
public class PersonSingleValueConverter extends AbstractSingleValueConverter {
@Override
public boolean canConvert(Class clazz) {
return clazz.equals(Person.class);
}
@Override
public Object fromString(String str) {
Person person=new Person();
//System.out.println("str+...."+str);
person.setName(str);
return person;
}
}
以上注意方法注意的一点是得重写Person的toString方法
@Override
public String toString() {
// TODO Auto-generated method stub
return getName();
}
2.Date的Converter
public class DateConverter implements Converter {
private Locale locale;
public DateConverter(Locale locale) {
super();
this.locale = locale;
}
public boolean canConvert(Class clazz) {
return Calendar.class.isAssignableFrom(clazz);
}
public void marshal(Object value, HierarchicalStreamWriter writer,
MarshallingContext context) {
Calendar calendar = (Calendar) value;
Date date = calendar.getTime();
DateFormat formatter = DateFormat.getDateInstance(DateFormat.FULL,
this.locale);
writer.setValue(formatter.format(date));
}
public Object unmarshal(HierarchicalStreamReader reader,
UnmarshallingContext context) {
GregorianCalendar calendar = new GregorianCalendar();
DateFormat formatter = DateFormat.getDateInstance(DateFormat.FULL,
this.locale);
try {
calendar.setTime(formatter.parse(reader.getValue()));
} catch (ParseException e) {
throw new ConversionException(e.getMessage(), e);
}
return calendar;
}
}
注意:
1.DateFormat 的实现有些事非线程安全的,因此不能把它作为Converter的成员变量
2.Calendar.class.isAssignableFrom(clazz);
isAssignableFrom: 判定此 Class
对象所表示的类或接口与指定的 Class
参数所表示的类或接口是否相同,或是否是其超类或超接口。
public class DateTest {
/**
* @param args
*/
public static void main(String[] args) {
// grabs the current date from the virtual machine
Calendar calendar = new GregorianCalendar();
// creates the xstream
XStream xStream = new XStream(new DomDriver());
// brazilian portuguese locale
xStream.registerConverter(new DateConverter(Locale.CHINA));
// prints the result
String xml=xStream.toXML(calendar);
System.out.println("xml:"+xml);
// loads the calendar from the string
Calendar loaded = (Calendar) xStream.fromXML(xml);
// prints using the system defined locale
System.out.println(DateFormat.getDateInstance(DateFormat.FULL).format(
loaded.getTime()));
}
}
3.Complex Converter复杂的转换器
public class Birthday {
private Person person;
private Calendar date;
private char gender;
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public Calendar getDate() {
return date;
}
public void setDate(Calendar date) {
this.date = date;
}
public char getGender() {
return gender;
}
public void setGenderMale() {
this.gender = 'm';
}
public void setGenderFemale() {
this.gender = 'f';
}
}
Birthday的Converter
public class BirthdayConverter implements Converter {
public boolean canConvert(Class clazz) {
return Birthday.class == clazz;
}
public void marshal(Object value, HierarchicalStreamWriter writer,
MarshallingContext context) {
Birthday birthday = (Birthday) value;
if (birthday.getGender() != '\0') {
writer.addAttribute("gender", Character.toString(birthday
.getGender()));
}
if (birthday.getPerson() != null) {
writer.startNode("person");
context.convertAnother(birthday.getPerson());
writer.endNode();
}
if (birthday.getDate() != null) {
writer.startNode("birth");
context.convertAnother(birthday.getDate());
writer.endNode();
}
}
public Object unmarshal(HierarchicalStreamReader reader,
UnmarshallingContext context) {
Birthday birthday = new Birthday();
String gender = reader.getAttribute("gender");
if (gender != null) {
if (gender.length() > 0) {
if (gender.charAt(0) == 'f') {
birthday.setGenderFemale();
} else if (gender.charAt(0)== 'm') {
birthday.setGenderMale();
} else {
throw new ConversionException("Invalid gender value: " + gender);
}
} else {
throw new ConversionException("Empty string is invalid gender value");
}
}
while (reader.hasMoreChildren()) {
reader.moveDown();
if ("person".equals(reader.getNodeName())) {
Person person = (Person)context.convertAnother(birthday, Person.class);
birthday.setPerson(person);
} else if ("birth".equals(reader.getNodeName())) {
Calendar date = (Calendar)context.convertAnother(birthday, Calendar.class);
birthday.setDate(date);
}
reader.moveUp();
}
return birthday;
}
}
看到了没,在有些属性为null时,抛出了自定义的异常,如果能保证所有的属性都是非空的,可以用下面的方式实现Converter
public class BirthdayConverter2 implements Converter {
public boolean canConvert(Class clazz) {
return Birthday.class == clazz;
}
public void marshal(Object value, HierarchicalStreamWriter writer,
MarshallingContext context) {
Birthday birthday = (Birthday)value;
writer.addAttribute("gender", Character.toString(birthday.getGender()));
writer.startNode("person");
context.convertAnother(birthday.getPerson());
writer.endNode();
writer.startNode("birth");
context.convertAnother(birthday.getDate());
writer.endNode();
}
public Object unmarshal(HierarchicalStreamReader reader,
UnmarshallingContext context) {
Birthday birthday = new Birthday();
if (reader.getAttribute("gender").charAt(0) == 'm') {
birthday.setGenderMale();
} else {
birthday.setGenderFemale();
}
reader.moveDown();
Person person = (Person)context.convertAnother(birthday, Person.class);
birthday.setPerson(person);
reader.moveUp();
reader.moveDown();
Calendar date = (Calendar)context.convertAnother(birthday, Calendar.class);
birthday.setDate(date);
reader.moveUp();
return birthday;
}
}
Birthday的测试类
public class BirthdayTest {
/**
* @param args
*/
public static void main(String[] args) {
Person person=new Person();
person.setName("张三");
Calendar date=Calendar.getInstance();
Birthday bir=new Birthday();
bir.setDate(date);
bir.setPerson(person);
bir.setGenderMale();
XStream stream=new XStream();
stream.alias("birthday", Birthday.class);
stream.alias("person", Person.class);
stream.registerConverter(new BirthdayConverter2());
stream.registerConverter(new DateConverter(Locale.CHINA));
String xml=stream.toXML(bir);
System.out.println("xml:"+xml);
Birthday b=(Birthday) stream.fromXML(xml);
System.out.println("person.name"+b.getPerson().getName());
System.out.println(".date:"+DateFormat.getDateInstance(DateFormat.FULL).format(
b.getDate().getTime()));
System.out.println(".gender:"+b.getGender());
}
}