文章出處

最近做webService報文轉換的公共接口使用到了XSream工具庫,寫個小總結備忘。。。

    XStream是一個可以將javaBean與XML雙向轉換的java類庫,本文內容基于xstream-1.4.4版本。所需maven依賴如下:

<dependency>
     <groupId>com.thoughtworks.xstream</groupId>
     <artifactId>xstream</artifactId>
     <version>1.4.4</version>
</dependency>

1.基本使用方法

    new Xstream().toXML(bean);

    使用該方式轉換的xml格式如下:

<org.xstream.test.People>
    <age>10</age>
    <name>sedric</name>
 </org.xstream.test.People>

    該格式由完整類名作為根節點,類成員變量名及變量值組成xml元素內容。

2.定義xml元素名、屬性名別名

普通方式:

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格式如下:

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

注解方式:

@XStreamAlias("People")
public class People {

@XStreamAlias("Age_Alias")
@XStreamAsAttribute
private int age;

@XStreamAsAttribute
private String name;

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

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

3.xstream定義別名單下劃線(_)雙下劃線(__)

xstream默認的轉換方式中定義了對特殊字符的轉換,代碼如下:

//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:

//使用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相同層次的元素時,可以在該成員變量使用該注解。

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

轉換的xml如下:

<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。

@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如下:

<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注解屬性:

//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屬性。代碼如下:

@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如下:

<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方法,只需注釋該方法中如下內容:

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實用指南


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()