XStream、Jaxb是java中用于对象xml序列化/反序列化 的经典开源项目,利用它们将对象转换成xml时,经常会遇到日期(Date)、数字按指定格式输出的需求,下面是使用示例:
一、日期字段格式化输出
1.1 xStream
1 XStream x = newXStream();2 x.registerConverter(new DateConverter("yyyy-MM-dd HH:mm:ss", null,TimeZone.getTimeZone("GMT+8")));
xStream默认使用UTC时间格式输出,上面的代码演示了如何按北京时间输出 yyyy-MM-dd HH:mm:ss 格式
1.2 jaxb
jaxb处理这个要麻烦一点,先要创建一个Adapter,下面是示例
1 packagecom.cnblogs.yjmyzz.test;2
3 importjava.text.DateFormat;4 importjava.text.SimpleDateFormat;5 importjava.util.Date;6
7 importjavax.xml.bind.annotation.adapters.XmlAdapter;8
9 public class JaxbDateAdapter extends XmlAdapter{10 static final String STANDARM_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";11
12 @Override13 public Date unmarshal(String v) throwsException {14 if (v == null) {15 return null;16 }17
18 DateFormat format = newSimpleDateFormat(STANDARM_DATE_FORMAT);19 returnformat.parse(v);20 }21
22 @Override23 public String marshal(Date v) throwsException {24 DateFormat format = newSimpleDateFormat(STANDARM_DATE_FORMAT);25 returnformat.format(v);26 }27 }
然后要处理的dto类,相应的Date字段的get方法上使用刚才这个Adapter
@XmlJavaTypeAdapter(JaxbDateAdapter.class)publicDate getCreateDate() {returncreateDate;
}
注:不要在private上使用,最好将注解打在get方法上,否则有可能报错。
这里,再给一个List类型的常见用法:
@XmlElementWrapper(name="details")
@XmlElement(name="detail")
public List getDetails() {
return details;
}
如果没有这二个注解,xml的结果类似:
...
...
...
...
加上这二个注释后,xml的结果类似:
...
...
...
...
二、数字格式化
假设我们要将一个Double型的成员,按中国货币的格式输出
2.1 xStream
默认的DoubleConverter满足不了要求,得从它派生一个子类来重写toString(Object obj)方法
1 packagecom.cnblogs.yjmyzz.test;2
3 importjava.text.NumberFormat;4 importjava.util.Locale;5
6 importcom.thoughtworks.xstream.converters.basic.DoubleConverter;7
8 public class DoubleToCurrencyStringConverter extendsDoubleConverter {9
10 NumberFormat format;11
12 publicDoubleToCurrencyStringConverter(Locale local) {13 format =NumberFormat.getCurrencyInstance(local);14 }15
16 publicString toString(Object obj) {17 returnformat.format(obj);18 }19
20 }
然后这样使用:
1 XStream x = newXStream();2 x.registerConverter(new DoubleToCurrencyStringConverter(Locale.CHINA));
2.2 Jaxb
仍然是按Adapter的老路,定义一个专用的Adapter
1 packagecom.cnblogs.yjmyzz.test;2
3 importjava.text.NumberFormat;4 importjava.util.Locale;5
6 importjavax.xml.bind.annotation.adapters.XmlAdapter;7
8 public class JaxbNumberAdapter extends XmlAdapter{9
10 @Override11 public Number unmarshal(String v) throwsException {12 if (v == null) {13 return null;14 }15 NumberFormat format =NumberFormat.getCurrencyInstance(Locale.CHINA);16 returnformat.parse(v);17 }18
19 @Override20 public String marshal(Number v) throwsException {21 NumberFormat format =NumberFormat.getCurrencyInstance(Locale.CHINA);22 returnformat.format(v);23 }24 }
然后在相关的Double字段的get方法上,用注解使用这个Adapter
1 @XmlJavaTypeAdapter(JaxbNumberAdapter.class)2 publicDouble getAmount() {3 returnamount;4 }
最后附一个完整的示例:
为演示效果,先定义一个Dto类:
1 packagecom.cnblogs.yjmyzz.test;2
3 importjava.io.Serializable;4 importjava.util.Date;5
6 importjavax.xml.bind.annotation.XmlRootElement;7 importjavax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;8 importcom.thoughtworks.xstream.annotations.XStreamAlias;9
10 @XmlRootElement(name = "sample")11 @XStreamAlias("sample")12 public class Sample implementsSerializable{13
14 private static final long serialVersionUID = -6271703229325404123L;15
16 privateDouble amount;17
18
19 privateDate createDate;20
21 @XmlJavaTypeAdapter(JaxbNumberAdapter.class)22 publicDouble getAmount() {23 returnamount;24 }25
26 public voidsetAmount(Double amount) {27 this.amount =amount;28 }29
30 @XmlJavaTypeAdapter(JaxbDateAdapter.class)31 publicDate getCreateDate() {32 returncreateDate;33 }34
35 public voidsetCreateDate(Date createDate) {36 this.createDate =createDate;37 }38
39 }
同时为了使用jaxb更方便,定义一个JaxbUtil辅助类
1 packagecom.cnblogs.yjmyzz.util;2
3 importjava.io.StringReader;4 importjava.io.StringWriter;5
6 importjavax.xml.bind.JAXBContext;7 importjavax.xml.bind.Marshaller;8 importjavax.xml.bind.Unmarshaller;9
10 public classJaxbUtil {11
12 public staticString toXml(Object obj) {13 return toXml(obj, "UTF-8", false);14 }15
16 public staticString toXml(Object obj, String encoding,17 booleanisFormatOutput) {18 String result = null;19 try{20 JAXBContext context =JAXBContext.newInstance(obj.getClass());21 Marshaller marshaller =context.createMarshaller();22 marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,23 isFormatOutput);24 marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding);25
26 StringWriter writer = newStringWriter();27 marshaller.marshal(obj, writer);28 result =writer.toString();29 } catch(Exception e) {30 e.printStackTrace();31 }32
33 returnresult;34 }35
36 @SuppressWarnings("unchecked")37 public static T toObject(String xml, Classc) {38 T t = null;39 try{40 JAXBContext context =JAXBContext.newInstance(c);41 Unmarshaller unmarshaller =context.createUnmarshaller();42 t = (T) unmarshaller.unmarshal(newStringReader(xml));43 } catch(Exception e) {44 e.printStackTrace();45 }46
47 returnt;48 }49 }
完整的单元测试如下:
1 packagecom.cnblogs.yjmyzz.test;2
3 importjava.util.Calendar;4 importjava.util.Locale;5 importjava.util.TimeZone;6 importorg.junit.Test;7 importcom.cnblogs.yjmyzz.util.JaxbUtil;8 importcom.thoughtworks.xstream.converters.basic.DateConverter;9 importcom.thoughtworks.xstream.XStream;10
11 public classXStreamAndJaxbTest {12
13 privateSample getSampleObj() {14 Calendar c =Calendar.getInstance(Locale.CHINA);15 c.set(2014, 9, 31, 0, 0, 0);16 Sample obj = newSample();17 obj.setCreateDate(c.getTime());18 obj.setAmount(1234.5678);19 returnobj;20 }21
22 @Test23 public voidtestXStream() {24 XStream x = newXStream();25 x.alias("sample", Sample.class);26 x.registerConverter(new DateConverter("yyyy-MM-dd HH:mm:ss", null,27 TimeZone.getTimeZone("GMT+8")));28 x.registerConverter(newDoubleToCurrencyStringConverter(Locale.CHINA));29 System.out.println("==> xstream ==>\n");30 System.out.println(x.toXML(getSampleObj()));31 System.out.println("\n\n");32 }33
34 @Test35 public voidtestJaxb() {36 System.out.println("==> jaxb ==>\n");37 System.out.println(JaxbUtil.toXml(getSampleObj(),"UTF-8",true));38 System.out.println("\n\n");39 }40
41 }
测试结果如下:
==> jaxb ==>
¥1,234.57
2014-10-31 00:00:00
==> xstream ==>
¥1,234.57
2014-10-31 00:00:00