首页 > 代码库 > XStream、JAXB 日期(Date)、数字(Number)格式化输出xml

XStream、JAXB 日期(Date)、数字(Number)格式化输出xml

XStream、Jaxb是java中用于对象xml序列化/反序列化 的经典开源项目,利用它们将对象转换成xml时,经常会遇到日期(Date)、数字按指定格式输出的需求,下面是使用示例:

一、日期字段格式化输出

1.1 xStream

1 XStream x = new XStream();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 package com.cnblogs.yjmyzz.test; 2  3 import java.text.DateFormat; 4 import java.text.SimpleDateFormat; 5 import java.util.Date; 6  7 import javax.xml.bind.annotation.adapters.XmlAdapter; 8  9 public class JaxbDateAdapter extends XmlAdapter<String, Date> {10     static final String STANDARM_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";11 12     @Override13     public Date unmarshal(String v) throws Exception {14         if (v == null) {15             return null;16         }17 18         DateFormat format = new SimpleDateFormat(STANDARM_DATE_FORMAT);19         return format.parse(v);20     }21 22     @Override23     public String marshal(Date v) throws Exception {24         DateFormat format = new SimpleDateFormat(STANDARM_DATE_FORMAT);25         return format.format(v);26     }27 }

然后要处理的dto类,相应的Date字段的get方法上使用刚才这个Adapter

    @XmlJavaTypeAdapter(JaxbDateAdapter.class)     public Date getCreateDate() {        return createDate;    }

注:不要在private上使用,最好将注解打在get方法上,否则有可能报错

 

二、数字格式化

假设我们要将一个Double型的成员,按中国货币的格式输出

2.1 xStream

默认的DoubleConverter满足不了要求,得从它派生一个子类来重写toString(Object obj)方法

 1 package com.cnblogs.yjmyzz.test; 2  3 import java.text.NumberFormat; 4 import java.util.Locale; 5  6 import com.thoughtworks.xstream.converters.basic.DoubleConverter; 7  8 public class DoubleToCurrencyStringConverter extends DoubleConverter { 9 10     NumberFormat format;11 12     public DoubleToCurrencyStringConverter(Locale local) {13         format = NumberFormat.getCurrencyInstance(local);14     }15 16     public String toString(Object obj) {17         return format.format(obj);18     }19 20 }

然后这样使用:

1         XStream x = new XStream();2         x.registerConverter(new DoubleToCurrencyStringConverter(Locale.CHINA));

2.2 Jaxb

仍然是按Adapter的老路,定义一个专用的Adapter

 1 package com.cnblogs.yjmyzz.test; 2  3 import java.text.NumberFormat; 4 import java.util.Locale; 5  6 import javax.xml.bind.annotation.adapters.XmlAdapter; 7  8 public class JaxbNumberAdapter extends XmlAdapter<String, Number> { 9 10     @Override11     public Number unmarshal(String v) throws Exception {12         if (v == null) {13             return null;14         }15         NumberFormat format = NumberFormat.getCurrencyInstance(Locale.CHINA);16         return format.parse(v);17     }18 19     @Override20     public String marshal(Number v) throws Exception {        21         NumberFormat format = NumberFormat.getCurrencyInstance(Locale.CHINA);22         return format.format(v);23     }24 }

然后在相关的Double字段的get方法上,用注解使用这个Adapter

1     @XmlJavaTypeAdapter(JaxbNumberAdapter.class) 2     public Double getAmount() {3         return amount;4     }

最后附一个完整的示例:

为演示效果,先定义一个Dto类:

 1 package com.cnblogs.yjmyzz.test; 2  3 import java.io.Serializable; 4 import java.util.Date; 5  6 import javax.xml.bind.annotation.XmlRootElement; 7 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; 8 import com.thoughtworks.xstream.annotations.XStreamAlias; 9 10 @XmlRootElement(name = "sample")11 @XStreamAlias("sample")12 public class Sample implements Serializable{    13     14     private static final long serialVersionUID = -6271703229325404123L;15 16     private Double amount;17     18     19     private Date createDate;20 21     @XmlJavaTypeAdapter(JaxbNumberAdapter.class) 22     public Double getAmount() {23         return amount;24     }25 26     public void setAmount(Double amount) {27         this.amount = amount;28     }29 30     @XmlJavaTypeAdapter(JaxbDateAdapter.class) 31     public Date getCreateDate() {32         return createDate;33     }34 35     public void setCreateDate(Date createDate) {36         this.createDate = createDate;37     }38 39 }

同时为了使用jaxb更方便,定义一个JaxbUtil辅助类

 1 package com.cnblogs.yjmyzz.util; 2  3 import java.io.StringReader; 4 import java.io.StringWriter; 5  6 import javax.xml.bind.JAXBContext; 7 import javax.xml.bind.Marshaller; 8 import javax.xml.bind.Unmarshaller; 9 10 public class JaxbUtil {11 12     public static String toXml(Object obj) {13         return toXml(obj, "UTF-8", false);14     }15 16     public static String toXml(Object obj, String encoding,17             boolean isFormatOutput) {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 = new StringWriter();27             marshaller.marshal(obj, writer);28             result = writer.toString();29         } catch (Exception e) {30             e.printStackTrace();31         }32 33         return result;34     }35 36     @SuppressWarnings("unchecked")37     public static <T> T toObject(String xml, Class<T> c) {38         T t = null;39         try {40             JAXBContext context = JAXBContext.newInstance(c);41             Unmarshaller unmarshaller = context.createUnmarshaller();42             t = (T) unmarshaller.unmarshal(new StringReader(xml));43         } catch (Exception e) {44             e.printStackTrace();45         }46 47         return t;48     }49 }

完整的单元测试如下:

 1 package com.cnblogs.yjmyzz.test; 2  3 import java.util.Calendar; 4 import java.util.Locale; 5 import java.util.TimeZone; 6 import org.junit.Test; 7 import com.cnblogs.yjmyzz.util.JaxbUtil; 8 import com.thoughtworks.xstream.converters.basic.DateConverter; 9 import com.thoughtworks.xstream.XStream;10 11 public class XStreamAndJaxbTest {12 13     private Sample getSampleObj() {14         Calendar c = Calendar.getInstance(Locale.CHINA);15         c.set(2014, 9, 31, 0, 0, 0);16         Sample obj = new Sample();17         obj.setCreateDate(c.getTime());18         obj.setAmount(1234.5678);19         return obj;20     }21 22     @Test23     public void testXStream() {        24         XStream x = new XStream();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(new DoubleToCurrencyStringConverter(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 void testJaxb() {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 ==>

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<sample>
<amount>¥1,234.57</amount>
<createDate>2014-10-31 00:00:00</createDate>
</sample>

 


==> xstream ==>

<sample>
<amount>¥1,234.57</amount>
<createDate>2014-10-31 00:00:00</createDate>
</sample>

 

XStream、JAXB 日期(Date)、数字(Number)格式化输出xml