XStream使用总结

最近做webService报文转换的公共接口使用到了XSream工具库,写个小总结备忘。。。

    XStream是一个可以将javaBean与XML双向转换的java类库,本文内容基于xstream-1.4.4版本。所需maven依赖如下:

1
2
3
4
5
< dependency >
      < groupId >com.thoughtworks.xstream</ groupId >
      < artifactId >xstream</ artifactId >
      < version >1.4.4</ version >
</ dependency >

1.基本使用方法

    new Xstream().toXML(bean);

    使用该方式转换的xml格式如下:

1
2
3
4
< org.xstream.test.People >
     < age >10</ age >
     < name >sedric</ name >
  </ org.xstream.test.People >

    该格式由完整类名作为根节点,类成员变量名及变量值组成xml元素内容。

2.定义xml元素名、属性名别名

普通方式:

1
2
3
4
5
6
xstream.useAttributeFor(People. class , "age" );
xstream.useAttributeFor(People. class , "name" );
//定义Class别名
xstream.alias( "People" , People. class );
//定义Field别名
xstream.aliasField( "Age_Alias" , People. class , "age" );

使用该方式转换的xml格式如下:

1
< People  Age__Alias="10" name="sedric"/>

注解方式:

1
2
3
4
5
6
7
8
9
@XStreamAlias ( "People" )
public  class  People {
 
@XStreamAlias ( "Age_Alias" )
@XStreamAsAttribute
private  int  age;
 
@XStreamAsAttribute
private  String name;

使用注解方式时必须指定xstream解析annotations,方式如下:

1
2
3
4
//指定所有class均解析annotations
xstream.autodetectAnnotations( true );
//指定指定class解析annotations
xstream.processAnnotations(People. class );

3.xstream定义别名单下划线(_)双下划线(__)

xstream默认的转换方式中定义了对特殊字符的转换,代码如下:

1
2
3
4
5
6
7
//XmlFriendlyNameCoder.encodeName(String name)
for  (; i < length; i++ ) {
             char  c = name.charAt(i);
             if  (c == '$'  || c == '_'  || c <= 27  || c >= 127 ) {
                 break ;
             }
  }

xstream对以上范围字符进行特殊字符转换,导致单下划线变为双下划线。解决方式:

    方法1:str.replaceAll(“__“,“_“);

    方法2:

1
2
3
4
//使用xstream自带的NoNameCoder构造xstream,该方式将导致所有特殊字符都不转义
XStream xstream = new  XStream( new  XppDriver( new  NoNameCoder()));
//使用Domdriver及NonameCoder构造xstream,该方式可以指定xml编码方式
XStream xstream = new  XStream( new  DomDriver( "UTF-8" , new  NoNameCoder()));

    方法3:自定义NameCoder,对指定特殊字符进行转换。

4.XStreamImplicit注解使用

    当需要将collection或map类型的成员变量中数据转换成xml相同层次的元素时,可以在该成员变量使用该注解。

1
2
@XStreamImplicit (itemFieldName = "List_Element" )
private  List<JP> jps;

转换的xml如下:

1
2
3
4
5
6
7
8
9
10
< People  Age_Alias="10" name="sedric">
< List_Element >
< gender >man</ gender >
< reason >人傻钱多</ reason >
</ List_Element >
< List_Element >
< gender >woman</ gender >
< reason >巧言令色</ reason >
</ List_Element >
</ People >

    XStreamImplicit注解有两个属性:itemFieldName是指当前集合数据转换为xml元素时的 elementName;keyFieldName在集合元素为复杂对象时,会使用集合元素的成员变量名作为元素的elementName,当集合元素为 基本数据类型及String类型时,keyFieldName指定的值将作为元素的elementName。

1
2
3
4
5
6
7
8
@XStreamImplicit (itemFieldName = "String_Element" , keyFieldName = "String_Field" )
private  List<String> stringList;
 
@XStreamImplicit (itemFieldName = "List_Element" , keyFieldName = "List_Field" )
private  List<JP> jps;
 
@XStreamImplicit (itemFieldName = "Map_Element" , keyFieldName = "Map_Field" )
private  Map<String, String> map;

转换的xml如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
< People  Age_Alias="10" name="sedric">
< String_Element >str1</ String_Element >
< String_Element >str2</ String_Element >
< List_Element >
< gender >man</ gender >
< reason >人傻钱多</ reason >
</ List_Element >
< List_Element >
< gender >woman</ gender >
< reason >巧言令色</ reason >
</ List_Element >
< Map_Element >value2</ Map_Element >
< Map_Element >value1</ Map_Element >
</ People >

5.XStreamConverter注解使用

    xstreamConvert用于指定class及Field的converter(转换方式)。

    xstreamConvert定义于class时,该class及其所有成员变量(递归,即成员变量是复合对象时该符合对象的成员变量)均 默认使用xstreamConvert指定的converter进行转换(满足converter.canConvert(Class type)时一定会使用指定的converter)。

    xstreamConvert定义与field时,该field如果是基本类型或String类型,满足canConvert(Class type)方法时使用该converter进行转换;如果是复合对象,则该对象所有成员变量(递归)满足canConvert(Class type)时使用该converter进行转换。

XStreamConverter注解属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//priority指定converter优先级,即当有多个converter均可转换当前对象时,只使用priority
//最大的converter。
int  priority() default  XStream.PRIORITY_NORMAL;
//以下属性在指定值时,将会在构造该converter时作为构造方法的参数传入。
Class<?>[] types() default  {};
String[] strings() default  {};
byte [] bytes() default  {};
char [] chars() default  {};
short [] shorts() default  {};
int [] ints() default  {};
long [] longs() default  {};
float [] floats() default  {};
double [] doubles() default  {};
boolean [] booleans() default  {};

对于converter构造参数较复杂,上述属性不能满足构造参数时,可以使用xstream.registerConverter(参数。。)或xstream.registerLocalConverter(参数。。)来注册converter。

6.xstream对泛型、接口、超类的支持

对于复合类型对象,xstream默认使用ReflectionConverter来进行对象转换。该converter中定义了当属性定义类型与运行时类型不一致时,将会给该元素添加一个class属性。代码如下:

1
2
3
4
5
6
7
8
9
10
11
@XStreamAlias ( "Generic" )
public  class  GenericTypeTest {
 
@XStreamAlias ( "People" )
private  People people;
 
           GenericTypeTest generic = new  GenericTypeTest();
            //SB是People的子类,SB中定义成员变量
  SB sb = new  SB( 50 , "sb" );
 
  generic.setPeople(sb);

转的xml如下:

1
2
3
4
5
6
< Generic >
< People  class="org.xstream.test.SB" Age_Alias="50" name="sb">
< gender >woman</ gender >
< reason >resson</ reason >
</ People >
</ Generic >

当转换xml不需要该class属性时,可以通过自定义converter实现。实现方式参照AbstractReflectionConverter.doMarshal方法,只需注释该方法中如下内容:

1
2
3
4
5
6
7
8
9
10
11
12
Class defaultType = mapper.defaultImplementationOf(fieldType);
if  (!actualType.equals(defaultType)) {
String serializedClassName = mapper.serializedClass(actualType);
f (!serializedClassName.equals(mapper.serializedClass(defaultType))) {
// String attributeName =
// mapper.aliasForSystemAttribute("class");
// if (attributeName != null) {
// writer.addAttribute(attributeName,
// serializedClassName);
// }
}
}

对于xml转javabean,xstream默认的所有converter均不支持泛型、接口。如果存在超类时,xml中存在子类属性时,转换将出现异常,不包含子类属性时,可转换成功。

原文链接

相关:XStream实用指南

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值