zoukankan      html  css  js  c++  java
  • 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     @Override
    13     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     @Override
    23     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方法上,否则有可能报错。

    这里,再给一个List<T>类型的常见用法:

    @XmlElementWrapper(name="details")
    @XmlElement(name="detail")
    public List<FSUDetail> getDetails() {
        return details;
    }

    如果没有这二个注解,xml的结果类似:

    <root>
    ...
        <details>...</details>
        <details>...</details>
    ...
    </root>
    加上这二个注释后,xml的结果类似:
    <root>
    ...
        <details>
            <detail>...</detail>
            <detail>...</detail>
        </details>    
    ...
    </root>

    二、数字格式化

    假设我们要将一个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     @Override
    11     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     @Override
    20     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     @Test
    23     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 ==>
    ");
    30         System.out.println(x.toXML(getSampleObj()));
    31         System.out.println("
    
    ");
    32     }
    33 
    34     @Test
    35     public void testJaxb() {
    36         System.out.println("==> jaxb ==>
    ");
    37         System.out.println(JaxbUtil.toXml(getSampleObj(),"UTF-8",true));
    38         System.out.println("
    
    ");
    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>

  • 相关阅读:
    Spring Session设计思路
    Jinja2 is a full-featured template engine for Python
    Computer Science:《The Essence of Winning and Losing》
    开源 敏捷 devops Lean Startup Huawei CRM
    BRMS ILOG
    日志易 IDS Snort 入侵检测
    理解和了解别人的正确姿势
    谷歌趋势 Google Trends
    OpenZipkin · A distributed tracing system
    Arthas OAM
  • 原文地址:https://www.cnblogs.com/yjmyzz/p/xstream-jaxb-format-date-and-number.html
Copyright © 2011-2022 走看看