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 ==>n");
30 System.out.println(x.toXML(getSampleObj()));
31 System.out.println("nn");
32 }
33
34 @Test
35 public void testJaxb() {
36 System.out.println("==> jaxb ==>n");
37 System.out.println(JaxbUtil.toXml(getSampleObj(),"UTF-8",true));
38 System.out.println("nn");
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>
- PhalApi-PHPExcel基于PhalApi的PHPExcel拓展
- [喵咪软件推荐(2)]全球服务器测速工具speedtest-cli
- 使用Keras创建一个卷积神经网络模型,可对手写数字进行识别
- 新生代的垃圾回收:Copy GC之基本原理
- [喵咪软件推荐(1)]全球国家信息库
- 一文教你在Python中打造你自己专属的面部识别系统
- [喵咪Liunx(6)]Nginx日志分析工具goaccess
- 用Atomic实现锁
- [喵咪Liunx(5)集群管理利器pssh
- synchronized关键字的语义
- [喵咪KafKa(3)]PHP拓展See-KafKa
- [喵咪KafKa(2)]单机模式运行KafKa
- 多线程内幕
- Otter-入门篇4(单向同步实践)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- A轮公司数据分析面试经验
- Pytorch转NCNN的流程记录
- 算法图解:如何找出栈中的最小值?
- 滴滴出行二面笔试题
- spring JdbcTemplate 查询,参数中使用BeanPropertyRowMapper的作用
- 百万级类别的分类模型的拆分训练
- 关于Spring定义的preDestroy修饰的方法不执行,有以下两种原因,总有一款适合你
- CSP201912-2-回收站选址题目解析-Java ,
- Spring boot框架快速入门
- SpringBoot 跨域问题:Access to XMLHttpRequest at ‘***‘ from origin ‘***‘ has been blocked by CORS policy
- 火车购票-CSP201609-2-Java
- 从后端开发人员的视角:最浅显的理解 Vue
- Sublime怎么默认显示文件路径
- Git 删除已提交的文件
- Sublime 怎么装SQL语法检测器