最近在项目中遇到了JAVA bean 和XML互转的需求, 本来准备循规蹈矩使用dom4j忽然想起来之前曾接触过的XStream, 一番研究豁然开朗,利器啊利器, 下来就XStream的一些用法与大家分享。

XStream是大名鼎鼎的thought works下的一个开源项目, 主要功能是提供JAVA bean 和XML文本之间的转换,另外还提供JAVA bean和JSON之间的转换,这个不在本次讨论的范围内。

XStream进行转换是非常简单的,对JAVA bean没有任何要求:

  • 不要求对private属性提供access方法(set/get)。
  • 不要求提供默认构造函数。
实际的代码操作就更简单了,在JAVA1.5以后XSteam也支持了annotation。 这时就只要在JAVA BEAN中添加若干annotation就可以了,当然如果不允许修改JAVA bean, 那XStream也提供register的方式,也是很简单的。 我准备在例子中体现一下的topic:
  • 基本转换
  • 对象起别名
  • 处理属性
  • 处理List
  • 忽略field
1. 基本转换

这是一个普通的JAVA bean:
package xstreamTest;
public class Person {  private String name;  private int age;  public int getAge() {  return age;  }  public void setAge(int age) {  this.age = age;  }  public void setName(String name) {  this.name = name;  }  public String getName() {  return this.name;  }
}

  转换代码是这样的:

XStream xstream = new XStream();
Person person = new Person();
person.setName("pli");
person.setAge(18);
System.out.println(xstream.toXML(person));  

我们得到了这样的结果:

<xstreamTest.Person>  <name>pli</name>  <age>18</age>
</xstreamTest.Person>  

有没有觉得很奇怪为什么会有“xstreamTest.Person”的标签?对照下上面提到的JAVA bean这个标签是来自于JAVA bean的类全路径的。
可是这个并不是我想要的啊,有没办法改变?有,简单吗? 简单!
2. 起别名
家丁我们希望将“xstreamTest.Person” 这个莫名其妙的element标签改为“person”我们应该这么做。
package xstreamTest;
@XStreamAlias("person")
public class Person {  private String name;  private int age;  public int getAge() {  return age;  }  public void setAge(int age) {  this.age = age;  }  public void setName(String name) {  this.name = name;  }  public String getName() {  return this.name;  }
}  

而执行代码会变成这样:

XStream xstream = new XStream();
xstream.autodetectAnnotations(true);
Person person = new Person();
person.setName("pli");
person.setAge(18);
System.out.println(xstream.toXML(person));  

这样我们就得到了想要的:

<person>  <name>pli</name>  <age>18</age>
</person>  

这里要提到的是“xstream.autodetectAnnotations(true);” 这句代码告诉XStream去解析JAVA bean中的annotation。这句代码有一个隐患,会在后面讨论。
别名可以改变任何你想在序列化时改变的对象名字,类,属性甚至包名,所用到的其实就是“XSstreamAlias”这个annotation。
3. 处理属性
如果想要将JAVA bean中的“age”属性作为XML中person标签的一个attribute该怎么办呢。
这里介绍另外一个annotation:@XStreamAsAttribute, 我们的JAVA bean变成了这样:
@XStreamAlias("person")
public class Person {  private String name;  @XStreamAsAttribute  private int age;  public int getAge() {  return age;  }  public void setAge(int age) {  this.age = age;  }  public void setName(String name) {  this.name = name;  }  public String getName() {  return this.name;  }
}  

结果是这样的:

<person age="18">  <name>pli</name>
</person>  

好玩吧。
4. 处理List
如果JAVA bean中有List是什么情形呢。
@XStreamAlias("person")
public class Person {  private String name;  @XStreamAsAttribute  private int age;  List<String> girlFriends;  public List<String> getGirlFriends() {  return girlFriends;  }  public void setGirlFriends(List<String> girlFriends) {  this.girlFriends = girlFriends;  }  public int getAge() {  return age;  }  public void setAge(int age) {  this.age = age;  }  public void setName(String name) {  this.name = name;  }  public String getName() {  return this.name;  }
}  

直接转换我们会得到这样的结果:

<person age="18">  <name>pli</name>  <girlFriends>  <string>YuanYuanGao</string>  <string>QiShu</string>  <string>BoZhiZhang</string>  </girlFriends>
</person>  

结果其实也不赖,XStream在这里提供了一个@XStreamImplicit(itemFieldName=***)的annotation来满足用户想将List的根节点去掉和改变列表名字的需求,对应到我们的例子上就是去掉<girlFriends>标签和改变"<string>".我们来看看效果。

@XStreamAlias("person")
public class Person {  private String name;  @XStreamAsAttribute  private int age;  @XStreamImplicit(itemFieldName="girl")  List<String> girlFriends;  public List<String> getGirlFriends() {  return girlFriends;  }  public void setGirlFriends(List<String> girlFriends) {  this.girlFriends = girlFriends;  }  public int getAge() {  return age;  }  public void setAge(int age) {  this.age = age;  }  public void setName(String name) {  this.name = name;  }  public String getName() {  return this.name;  }
}  

结果是这样:

<person age="18">  <name>pli</name>  <girl>YuanYuanGao</girl>  <girl>QiShu</girl>  <girl>BoZhiZhang</girl>
</person>

5. 忽略属性
如果在JAVA bean中有些属性不想被序列化,XStream提供了解决这个需求的annotation: @XStreamOmitField
比如说不想讲girlfriends这个List序列化
@XStreamAlias("person")
public class Person {  private String name;  @XStreamAsAttribute  private int age;  @XStreamImplicit(itemFieldName="girl")  @XStreamOmitField  List<String> girlFriends;  public List<String> getGirlFriends() {  return girlFriends;  }  public void setGirlFriends(List<String> girlFriends) {  this.girlFriends = girlFriends;  }  public int getAge() {  return age;  }  public void setAge(int age) {  this.age = age;  }  public void setName(String name) {  this.name = name;  }  public String getName() {  return this.name;  }
}  

结果是这样:

<person age="18">  <name>pli</name>
</person> 

6. Converter
Converter这个是属于XStream中的高级特性了,用于基本功能不能满足的情况下让客户自己定制序列化/反系列化的细节,我们还是通过一个例子进行说明。
假如我要往JAVA bean中添加一个类型为Date的属性:
@XStreamAlias("person")
public class Person {  private String name;  @XStreamAsAttribute  private int age;  @XStreamImplicit(itemFieldName="girl")  @XStreamOmitField  List<String> girlFriends;  Date birthday;  public Date getBirthday() {  return birthday;  }  public void setBirthday(Date birthday) {  this.birthday = birthday;  }  public List<String> getGirlFriends() {  return girlFriends;  }  public void setGirlFriends(List<String> girlFriends) {  this.girlFriends = girlFriends;  }  public int getAge() {  return age;  }  public void setAge(int age) {  this.age = age;  }  public void setName(String name) {  this.name = name;  }  public String getName() {  return this.name;  }
}  

看看直接序列化的结果:

<person age="18">  <name>pli</name>  <birthday>2012-08-04 04:35:01.857 UTC</birthday>
</person>

还不错,但是生日只需要年月日就行了,没必要精确到毫秒,这怎么办呢,只能使用converter,我们这是就需要写代码了。

public class DateConverter implements Converter {  @Override  public boolean canConvert(Class clazz) {  return (Date.class).equals(clazz);  }  @Override  public void marshal(Object object, HierarchicalStreamWriter writer,  MarshallingContext context) {  Date date = (Date) object;  Calendar calendar = Calendar.getInstance();  calendar.setTime(date);  SimpleDateFormat format = new SimpleDateFormat("yyyy-mm-dd");  writer.setValue(format.format(calendar.getTime()));  }  @Override  public Object unmarshal(HierarchicalStreamReader arg0,  UnmarshallingContext arg1) {  return null;  }
}  

稍微解释下这段代码:DateConverter 实现了借口Converter,实现了接口中的三个方法:
  • public boolean canConvert(Class clazz) 用来检测本converter是否能够转换输入的类型。
  • public void marshal(Object object, HierarchicalStreamWriter writer,MarshallingContext context) 序列化的方法(JAVA bean --> XML)
  • public Object unmarshal(HierarchicalStreamReader arg0, UnmarshallingContext arg1) 反序列化的方法。因为本例用不到所以没有实现。
此时我们的JAVA bean也要相应改变:
@XStreamAlias("person")
public class Person {  private String name;  @XStreamAsAttribute  private int age;  @XStreamImplicit(itemFieldName="girl")  @XStreamOmitField  List<String> girlFriends;  @XStreamConverter(value=DateConverter.class)  Date birthday;  public Date getBirthday() {  return birthday;  }  public void setBirthday(Date birthday) {  this.birthday = birthday;  }  public List<String> getGirlFriends() {  return girlFriends;  }  public void setGirlFriends(List<String> girlFriends) {  this.girlFriends = girlFriends;  }  public int getAge() {  return age;  }  public void setAge(int age) {  this.age = age;  }  public void setName(String name) {  this.name = name;  }  public String getName() {  return this.name;  }
}  

看看结果:

<person age="18">  <name>pli</name>  <birthday>2012-50-04</birthday>
</person>  

另外在这里简单说说converter的原理:
其实XStream转换过程就是执行一个个converter的过程,只不过使用的大部分converter都是内建好的,XStream遇到一个待转换的object首先去查找能够转换这个object的转换器(converter)怎么找呢,就是通过converter的canConvert(Class clazz)这个方法,返回为true就是可以转换。明白了吧。
XStream的限制:
Xstream已经是很不错的东西了,如果真要找不足,我发现有两点。
1. 反序列化的时候无法使用autodetectAnnotations()方法通知XStream对象去识别annotation。
还记的前面代码中xstream.autodetectAnnotations(true); 吗, 这句代码的意思是告诉XStream对象需要自动识别annotation, 这在序列化(JAVA bean-->XML)的时候没什么问题。但是在反序列化的时候就有问题了,原因官网上说的比较模糊,总之就是不行,只能通过xstream.processAnnotations(Class clazz) 来显式的注册需要使用annotation的类才行,如果JAVA bean很多就会比较麻烦。但一般来说JAVA bean在代码组织结构中都比较集中,如放在听一个package下,这样也好办,可以再程序中将该package下的JAVA bean都获取,然后使用xstream.processAnnotations(Class[] clazzs) 批量注册。
2. Null 属性无法被序列化。
之前举的例子JAVA bean中的属性都是被初始化以后才进行序列化的,如果没有初始化就进行序列化会怎样呢 ,还是举个例子
@XStreamAlias("person")
public class Person {  private String name = "pli";  @XStreamAsAttribute  private int age = 19;  @XStreamImplicit(itemFieldName="girl")  @XStreamOmitField  List<String> girlFriends;  @XStreamConverter(value=DateConverter.class)  Date birthday = new Date();  public Date getBirthday() {  return birthday;  }  public void setBirthday(Date birthday) {  this.birthday = birthday;  }  public List<String> getGirlFriends() {  return girlFriends;  }  public void setGirlFriends(List<String> girlFriends) {  this.girlFriends = girlFriends;  }  public int getAge() {  return age;  }  public void setAge(int age) {  this.age = age;  }  public void setName(String name) {  this.name = name;  }  public String getName() {  return this.name;  }
}  

我想将其它属性都进行了初始化但是没有将girlFriends这个属性初始化,即使说girlFriends==null. 序列化以后会怎样呢?

<person age="18">  <name>pli</name>  <birthday>2012-36-04</birthday>
</person>

girlFriends这个属性压根就没有被序列化,其实我是想让它序列化成这个样子:

<person age="18">  <name>pli</name>  <birthday>2012-36-04</birthday>  <girlFriends/>
</person>  

原文:http://blog.csdn.net/pushme_pli/article/details/7829621

转载于:https://www.cnblogs.com/tytr/p/8134006.html

JAVA bean与XML互转的利器---XStream相关推荐

  1. java bean与xml转换_Java Bean与xml互相转换的方法分析

    本文实例讲述了Java Bean与xml互相转换的方法.分享给大家供大家参考,具体如下: XML和Java Bean互相转换是一个很有用的功能,因为两者有着前后合作的关系,但解析的过程比较痛苦.下面介 ...

  2. JAVA Bean和XML之间的相互转换 - XStream简单入门

    JAVA Bean和XML之间的相互转换 - XStream简单入门 背景介绍 XStream的简介 注解简介 应用实例 背景介绍 我们在工作中经常 遇到文件解析为数据或者数据转化为xml文件的情况, ...

  3. xml java jaxb_JAXB java类与xml互转

    JAXB(Java Architecture for XML Binding) 是一个业界的标准,是一项可以根据XML Schema产生Java类的技术.该过程中,JAXB也提供了将XML实例文档反向 ...

  4. android 中XML和对象转换利器Xstream的使用

    XStream框架: 虽说pull dom dom4j等优秀的xml解析工具使用非常广泛,但对于复杂庞大的数据交互来说,使用它们无疑让你倍加痛苦,你可能大部分精力都放在无聊繁琐的解析和拼装上,如果接口 ...

  5. java 中 Object XML 互转,最终选择Xstream

    前言 spring boot 2.0.0 RELEASE maven 3.5.0 项目中需要进行 Object 与 XML 的互转.为此尝试了几个互转工具,进行记录. 耗费了一天的时间,将Faster ...

  6. java json与xml互转工具类

    部分代码参考:https://blog.csdn.net/CDWLX/article/details/119038509 工具类 public class XmlMutualConversionJso ...

  7. Java中操作Xml使用备忘

    List item 文章目录 Java中操作Xml使用备忘 1. Hutool中XmlUtil的使用简介 2. Hutool中XmlUtil快速读取Xml字符串某个节点值 [简单取值时,推荐使用] 2 ...

  8. java接口返回xml格式_xml格式接口数据编程实战

    系统对外提供接口,或者系统调用外部接口,常常会使用xml格式作为接口数据传输格式(json数据,txt文本数据亦可),下面讲讲xml数据的生成和解析. 首先讲讲xml数据生成,通常可以用两种方法,使用 ...

  9. Java JSON、XML文件/字符串与Bean对象互转解析

    前言      在做web或者其他项目中,JSON与XML格式的数据是大家经常会碰见的2种.在与各种平台做数据对接的时候,JSON与XML格式也是基本的数据传递格式,本文主要简单的介绍JSON/XML ...

  10. Java Jaxb JavaBean与XML互转

    1.Jaxb - Java Arcitecture for XML Binding 是业界的一个标准,是一项能够依据XML Schema产生Java类的技术. Jaxb2.0是Jdk1.6的组成部分. ...

最新文章

  1. 计算的极限(零):逻辑与图灵机
  2. 通用窗口类 Inventory Pro 2.1.2 Demo1(下)
  3. axure命令行_Axure完成前端开发可行性探索
  4. pytorch笔记 torch.clamp(截取上下限)
  5. oracle中的greatest,ORACLE 内置函数之 GREATEST 和 LEAST(转)
  6. POJ 2323 贪心
  7. Linux 命令行上执行多个命令(分隔符简介使用)
  8. jni c call java_Java通过-jni调用c语言
  9. 技嘉注入usb 3.0工具_技嘉怎么安装win10系统 技嘉安装win10系统步骤【图文介绍】...
  10. Spring Boot 实用开发技巧————Eclipse 远程调试
  11. java quartz Scheduler 操作Trigger
  12. ASSERT报错:error C2664: “AfxAssertFailedLine”: 不能将参数 1 从“TCHAR []”转换为“LPCSTR”...
  13. mysql的半同步复制
  14. 常见input输入框 点击 发光白色外阴影 focus
  15. struct过滤器和拦截器的区别
  16. windows下的Oracle数据库安装教程
  17. 读:H2-MIL: Exploring Hierarchical Representation with Heterogeneous Multiple Instance Learning for...
  18. macbook proa1708_MacBook Pro 2017 A1708自己更换电池
  19. su: Authentication failure问题
  20. 第八次前端培训(JavaScript)

热门文章

  1. 2015-FCN论文翻译
  2. opencv python安装_Python 安装 第三方库的安装技巧
  3. 浏览器接收响应消息并显示内容
  4. Mysql短连接风暴
  5. kafka处理大数据包
  6. 从0开始html前端页面开发_HTML各标签介绍
  7. python基础学习笔记4--抽象
  8. 详析Exchange 2007/2010 SSL证书如何安装
  9. rhel 5.3 nis 服务器搭建 详细(原创)
  10. python selenium爬虫工具