作者:empty 出版社:empty |
Xstream使用介绍
1.Xstream介绍
1.Xstream介绍
Xstream是一种OXMapping 技术,是用来处理XML文件序列化的框架,在将JavaBean序列化,或将XML文件反序列化的时候,不需要其它辅助类和映射文件,使得XML序列化不再繁索。Xstream也可以将JavaBean序列化成Json或反序列化,使用非常方便
2.Xstream简单例子
class Person//JavaBean实体类
{
private String name;
private int age;
public Person(String name,int age)
{
this.name=name;
this.age=age;
}
@Override
public String toString()
{
return Person [name= + name + , age= + age + ] ;
}
}
public class Test
{
public static void main(String[] args)
{
Person bean=new Person( 张三 ,19);
XStream xstream = new XStream();
//XML序列化
String xml = xstream.toXML(bean);
System.out.println(xml);
//XML反序列化
bean=(Person)xstream.fromXML(xml);
System.out.println(bean);
xstream = new XStream(new JettisonMappedXmlDriver());
xstream.setMode(XStream.NO_REFERENCES);
//Json序列化
String json=xstream.toXML(bean);
System.out.println(json);
//Json反序列
bean=(Person)xstream.fromXML(json);
System.out.println(bean);
}
}
程序运行结果:
test.Person>
name>张三 /name>
age>19 /age>
/test.Person>
Person [name=张三, age=19]
{ test.Person :{ name : 张三 , age :19}}
Person [name=张三, age=19
2.工程集成
不需要在配置文件中进行额外配置,只需要往工程中导入jar包即可,我所使用的jar包为:
3.Xstream使用
1.Xstream序列化重命名
为包重命名:Xstream.aliasPackage()方法
public class Test
{
public static void main(String[] args)
{
Person bean=new Person( 张三 ,19);
XStream xstream = new XStream();
xstream.aliasPackage( com.lzw , test );//为包名称重命名
//序列化
String xml = xstream.toXML(bean);
System.out.println(xml);
//反序列化
bean=(Person)xstream.fromXML(xml);
System.out.println(bean);
}
}
程序运行结果:
com.lzw.Person>
name>张三 /name>
age>19 /age>
/com.lzw.Person>
Person [name=张三, age=19]
为类重命名:Xstream.alias()方法
public class Test
{
public static void main(String[] args)
{
Person bean=new Person( 张三 ,19);
XStream xstream = new XStream();
xstream.alias( 人 , Person.class);//为类名节点重命名
//序列化
String xml = xstream.toXML(bean);
System.out.println(xml);
//反序列化
bean=(Person)xstream.fromXML(xml);
System.out.println(bean);
}
}
程序运行结果:
人>
name>张三 /name>
age>19 /age>
/人>
Person [name=张三, age=19]
为字段重命名:Xstream.aliasField()方法
public class Test
{
public static void main(String[] args)
{
Person bean=new Person( 张三 ,19);
XStream xstream = new XStream();
xstream.aliasField( 姓名 , Person.class, name );//为类的字段节点重命名
xstream.aliasField( 年龄 , Person.class, age );//为类的字段节点重命名
//序列化
String xml = xstream.toXML(bean);
System.out.println(xml);
//反序列化
bean=(Person)xstream.fromXML(xml);
System.out.println(bean);
}
}
程序运行结果:
test.Person>
姓名>张三 /姓名>
年龄>19 /年龄>
/test.Person>
Person [name=张三, age=19]
省略集合根节点:Xstream.addImplicitCollection()方法
class Person
{
private String name;
private int age;
private List friends;
public Person(String name, int age, String... friends)
{
this.name = name;
this.age = age;
this.friends = Arrays.asList(friends);
}
@Override
public String toString()
{
return Person [name= + name + , age= + age + , friends= + friends + ] ;
}
}
public class Test
{
public static void main(String[] args)
{
Person bean =new Person( 张三 ,19, 李四 , 王五 , 赵六 );
XStream xstream = new XStream();
xstream.addImplicitCollection(Person.class, friends );//省略集合根节点
//序列化
String xml = xstream.toXML(bean);
System.out.println(xml);
//反序列化
bean=(Person)xstream.fromXML(xml);
System.out.println(bean);
}
}
程序运行结果:
test.Person>
name>张三 /name>
age>19 /age>
string>李四 /string>
string>王五 /string>
string>赵六 /string>
/test.Person>
Person [name=张三, age=19, friends=[李四, 王五, 赵六]]
把字段节点设置成属性:Xstream.useAttributeFor()方法
public class Test
{
public static void main(String[] args)
{
Person bean =new Person( 张三 ,19, 李四 , 王五 , 赵六 );
XStream xstream = new XStream();
xstream.useAttributeFor(Person.class, name );//把字段节点设置成属性
//序列化
String xml = xstream.toXML(bean);
System.out.println(xml);
//反序列化
bean=(Person)xstream.fromXML(xml);
System.out.println(bean);
}
}
程序运行结果:
test.Person name= 张三 >
age>19 /age>
friends class= java.util.Arrays$ArrayList >
a class= string-array >
string>李四 /string>
string>王五 /string>
string>赵六 /string>
/a>
/friends>
/test.Person>
Person [name=张三, age=19, friends=[李四, 王五, 赵六]]
隐藏字段:xstream.omitField()方法
public class Test
{
public static void main(String[] args)
{
Person bean =new Person( 张三 ,19, 李四 , 王五 , 赵六 );
XStream xstream = new XStream();
xstream.omitField(Person.class, friends );//把字段节点隐藏
//序列化
String xml = xstream.toXML(bean);
System.out.println(xml);
//反序列化
bean=(Person)xstream.fromXML(xml);
System.out.println(bean);
}
}
程序运行结果:
test.Person>
name>张三 /name>
age>19 /age>
/test.Person>
Person [name=张三, age=19, friends=null]
2.Xstream注解的使用
设置Xstream应用注解
使用Xstream注解前需要对Xstream进行配置,可以使用两种方式:应用某个JavaBean类的注解或自动使用JavaBean类的注解。代码如下:
XStream xstream = new XStream();
xstream.processAnnotations(Person.class);//应用Person类的注解
xstream.autodetectAnnotations(true);//自动检测注解
重命名注解:@XStreamAlias()
@XStreamAlias( 人 )
class Person
{
@XStreamAlias( 姓名 )
private String name;
@XStreamAlias( 年龄 )
private int age;
@XStreamAlias( 朋友 )
private List friends;
public Person(String name, int age, String... friends)
{
this.name = name;
this.age = age;
this.friends = Arrays.asList(friends);
}
@Override
public String toString()
{
return Person [name= + name + , age= + age + , friends= + friends + ] ;
}
}
程序运行结果:
人>
姓名>张三 /姓名>
年龄>19 /年龄>
朋友 class= java.util.Arrays$ArrayList >
a class= string-array >
string>李四 /string>
string>王五 /string>
string>赵六 /string>
/a>
/朋友>
/人>
Person [name=张三, age=19, friends=[李四, 王五, 赵六]]
省略集合根节点:@XStreamImplicit
class Person
{
private String name;
private int age;
//@XStreamImplicit//只隐藏集合根节点
@XStreamImplicit(itemFieldName= 朋友 )//设置重复的节点名,可能会导致无法反序列化
private List String> friends;
public Person(String name, int age, String... friends)
{
this.name = name;
this.age = age;
this.friends = Arrays.asList(friends);
}
@Override
public String toString()
{
return Person [name= + name + , age= + age + , friends= + friends + ] ;
}
}
程序运行结果:
test.Person>
name>张三 /name>
age>19 /age>
朋友>李四 /朋友>
朋友>王五 /朋友>
朋友>赵六 /朋友>
/test.Person>
Person [name=张三, age=19, friends=[李四, 王五, 赵六]]
把字段节点设置成属性:@XStreamAsAttribute
class Person
{
@XStreamAsAttribute
private String name;
@XStreamAsAttribute
private int age;
private List String> friends;
public Person(String name, int age, String... friends)
{
this.name = name;
this.age = age;
this.friends = Arrays.asList(friends);
}
@Override
public String toString()
{
return Person [name= + name + , age= + age + , friends= + friends + ] ;
}
}
程序运行结果:
test.Person name= 张三 age= 19 >
friends class= java.util.Arrays$ArrayList >
a class= string-array >
string>李四 /string>
string>王五 /string>
string>赵六 /string>
/a>
/friends>
/test.Person>
Person [name=张三, age=19, friends=[李四, 王五, 赵六]]
隐藏字段:@XStreamOmitField
class Person
{
private String name;
private int age;
@XStreamOmitField
private List String> friends;
public Person(String name, int age, String... friends)
{
this.name = name;
this.age = age;
this.friends = Arrays.asList(friends);
}
@Override
public String toString()
{
return Person [name= + name + , age= + age + , friends= + friends + ] ;
}
}
程序运行结果:
test.Person>
name>张三 /name>
age>19 /age>
/test.Person>
Person [name=张三, age=19, friends=null]
设置转换器:@XStreamConverter()
class Person
{
private String name;
private int age;
@XStreamConverter(value=BooleanConverter.class,booleans={false},strings={ 男 , 女 })
private boolean sex;
public Person(String name, int age, boolean sex)
{
this.name = name;
this.age = age;
this.sex=sex;
}
@Override
public String toString()
{
return Person [name= + name + , age= + age + , sex= + sex + ] ;
}
}
程序运行结果:
test.Person>
name>张三 /name>
age>19 /age>
sex>男 /sex>
/test.Person>
Person [name=张三, age=19, sex=true]
3.Xstream自定义的转换器
Xstream自带的转换器
Xstream内部有许多转换器,用于JavaBean对象到XML或Json之间的转换。这些转换器的详细信息网址:http://xstream.codehaus.org/converters.html
使用自定义的转换器
class Person
{
private String name;
private int age;
public Person(String name, int age)
{
this.name = name;
this.age = age;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public int getAge()
{
return age;
}
public void setAge(int age)
{
this.age = age;
}
@Override
public String toString()
{
return Person [name= + name + , age= + age + ] ;
}
}
public class PersonConverter implements Converter
{
@Override//定义转换器能转换的JavaBean类型
public boolean canConvert(Class type)
{
return type.equals(Person.class);
}
@Override//把对象序列化成XML或Json
public void marshal(Object value, HierarchicalStreamWriter writer,
MarshallingContext context)
{
Person person = (Person) value;
writer.startNode( 姓名 );
writer.setValue(person.getName());
writer.endNode();
writer.startNode( 年龄 );
writer.setValue(person.getAge()+ );
writer.endNode();
writer.startNode( 转换器 );
writer.setValue( 自定义的转换器 );
writer.endNode();
}
@Override//把XML或Json反序列化成对象
public Object unmarshal(HierarchicalStreamReader reader,
UnmarshallingContext context)
{
Person person = new Person( ,-1);
reader.moveDown();
person.setName(reader.getValue());
reader.moveUp();
reader.moveDown();
person.setAge(Integer.parseInt(reader.getValue()));
reader.moveUp();
return person;
}
}
public class Test
{
public static void main(String[] args)
{
Person bean =new Person( 张三 ,19);
XStream xstream = new XStream();
xstream.registerConverter(new PersonConverter());//注册转换器
//序列化
String xml = xstream.toXML(bean);
System.out.println(xml);
//反序列化
bean=(Person)xstream.fromXML(xml);
System.out.println(bean);
}
}
程序运行结果:
test.Person>
姓名>张三 /姓名>
年龄>19 /年龄>
转换器>自定义的转换器 /转换器>
/test.Person>
Person [name=张三, age=19]
常用的转换器接口与抽象类
SingleValueConverter:单值转换接口
AbstractSingleValueConverter:单值转换抽象类
Converter:常规转换器接口
4.Xstream对象流的使用
Xstream对象输出流
class Person
{
private String name;
private int age;
public Person(String name, int age)
{
this.name = name;
this.age = age;
}
}
public class Test
{
public static void main(String[] args) throws IOException
{
XStream xstream = new XStream();
ObjectOutputStream out = xstream.createObjectOutputStream(System.out);
out.writeObject(new Person( 张三 ,12));
out.writeObject(new Person( 李四 ,19));
out.writeObject( Hello );
out.writeInt(12345);
out.close();
}
}
程序运行结果:
object-stream>
test.Person>
name>张三 /name>
age>12 /age>
/test.Person>
test.Person>
name>李四 /name>
age>19 /age>
/test.Person>
string>Hello /string>
int>12345 /int>
/object-stream>
注意:
XStream对象流是通过标准java.io.ObjectOutputStream和java.io.ObjectInputStream对象。
因为XML文档只能有一个根节点,必须包装在一个序列化的所有元素 额外的根节点。 这个根节点默认 object-stream > 上面的例子所示。
Xstream对象输出流
class Person
{
private String name;
private int age;
public Person(String name, int age)
{
this.name = name;
this.age = age;
}
@Override
public String toString()
{
return Person [name= + name + , age= + age + ] ;
}
}
public class Test
{
public static void main(String[] args) throws IOException, ClassNotFoundException
{
String s= object-stream>
test.Person> name>张三 /name> age>12 /age> /test.Person>
int>12345 /int> /object-stream> ;
StringReader reader = new StringReader(s);
XStream xstream = new XStream();
ObjectInputStream in = xstream.createObjectInputStream(reader);
System.out.println((Person) in.readObject());
System.out.println(in.readInt());
}
}
程序运行结果:
Person [name=张三, age=12]
12345
5.Xstream持久化API
保存JavaBean对象
class Person
{
private String name;
private int age;
public Person(String name, int age)
{
this.name = name;
this.age = age;
}
@Override
public String toString()
{
return Person [name= + name + , age= + age + ] ;
}
}
public class Test
{
public static void main(String[] args) throws IOException, ClassNotFoundException
{
PersistenceStrategy strategy = new FilePersistenceStrategy(new File( D: tmp ));
List list = new XmlArrayList(strategy);
list.add(new Person( 张三 ,13));//保存数据
list.add(new Person( 李四 ,21));
list.add(new Person( 王五 ,17));
}
}
程序运行结果:
如果我们检查D: tmp目录,有三个文件:int@0.xml、int@1.xml、int@2.xml;每个对象都被序列化到XML文件里。
读取并删除JavaBean对象
public class Test
{
public static void main(String[] args) throws IOException, ClassNotFoundException
{
PersistenceStrategy strategy = new FilePersistenceStrategy(new File( D: tmp ));
List list = new XmlArrayList(strategy);
for (Iterator it = list.iterator(); it.hasNext();)
{
System.out.println((Person) it.next());
it.remove();//删除对象序列化文件
}
}
}
程序运行结果:
Person [name=张三, age=13]
Person [name=李四, age=21]
Person [name=王五, age=17]
6.Xstream操作Json
Xstream序列化Json的重命名
@XStreamAlias( 人 )
class Person
{
@XStreamAlias( 姓名 )
private String name;
@XStreamAlias( 年龄 )
private int age;
public Person(String name, int age)
{
this.name = name;
this.age = age;
}
@Override
public String toString()
{
return Person [name= + name + , age= + age + ] ;
}
}
public class Test
{
public static void main(String[] args)
{
Person bean=new Person( 张三 ,19);
XStream xstream = new XStream(new JettisonMappedXmlDriver());//设置Json解析器
xstream.autodetectAnnotations(true);
//Json序列化
String xml = xstream.toXML(bean);
System.out.println(xml);
//Json反序列化
bean=(Person)xstream.fromXML(xml);
System.out.println(bean);
}
}
程序运行结果:
{ 人 :{ 姓名 : 张三 , 年龄 :19}}
Person [name=张三, age=19]
注意:Xstream序列化Json的重命名的方式与其序列化成XML的方式一样!
去掉序列化Json的根节点
class Person
{
private String name;
private int age;
public Person(String name, int age)
{
this.name = name;
this.age = age;
}
@Override
public String toString()
{
return Person [name= + name + , age= + age + ] ;
}
}
public class Test00
{
public static void main(String[] args)
{
Person bean=new Person( 张三 ,19);
XStream xstream = new XStream(new JsonHierarchicalStreamDriver()
{
public HierarchicalStreamWriter createWriter(Writer writer)
{
return new JsonWriter(writer, JsonWriter.DROP_ROOT_MODE);
}
});
//Json序列化
String xml = xstream.toXML(bean);
System.out.println(xml);
}
}
程序运行结果:
{
name : 张三 ,
age : 19
}
注意:去掉根节点后的Json串是不能反序列化的,因为XStream 不知道它的类型。
Json的解析器区别
前面两个例子使用了不同的Json解析器,这里说明他们的不同之处:
JettisonMappedXmlDriver:是支持序列化和反序列化Json的。
JsonHierarchicalStreamDriver:只支持序列化,不支持反序列化。
4.处理复杂xml的几种情况
1.bean里包含List bean>的情况
?xml version='1.0' encoding='UTF-8'?>
room>
door>我是门 /door>
windows>
window>
id>123 /id>
size>111 /size>
/window>
window>
id>456 /id>
size>222 /size>
/window>
/windows>
/room>
首先创建bean:room和window
public class Room {
public String door = null;
public List Window> windows = new ArrayList Window>();
public String getDoor() {
return door;
}
public void setDoor(String door) {
this.door = door;
}
public List Window> getWindows() {
return windows;
}
public void setWindows(List Window> windows) {
this.windows = windows;
}
}
public class Window {
public int id = 0;
public String size = null;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getSize() {
return size;
}
public void setSize(String size) {
this.size = size;
}
}
然后采用如下方法解析
//设置xml处理器
XStream xstream = new XStream();
//设置属性
xstream.alias( room ,Room.class);//把默认的testService1. Room转换成Room 或者在Room类上加 @XStreamAlias( Room )
xstream.alias( window ,Window.class);
xstream.processAnnotations(Room.class);//应用Room类的注解
xstream.autodetectAnnotations(true);//自动检测注解
Room room = (Room)xstream.fromXML(xml);
2.xml转成List bean>的情况
?xml version='1.0' encoding='UTF-8'?>
windows>
window>
id>123 /id>
size>111 /size>
/window>
window>
id>456 /id>
size>222 /size>
/window>
/windows>
首先创建bean:window
public class Window {
public int id = 0;
public String size = null;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getSize() {
return size;
}
public void setSize(String size) {
this.size = size;
}
}
然后采用如下方法解析
//设置xml处理器
XStream xstream = new XStream();
//设置属性
xstream.alias( window ,Window.class);
xstream.autodetectAnnotations(true);//自动检测注解
xstream.alias( windows , ArrayList.class); //设置windows为list节点
Room room = (Room)xstream.fromXML(xml);
List Window> window = (List Window>)xstream.fromXML(xml);
3.xml里包含多个bean,但是只解析其中的一个
?xml version='1.0' encoding='UTF-8'?>
data>
room>
door>我是门 /door>
/room>
window>
id>123 /id>
size>111 /size>
/window>
/data>
只解析room而不解析window
创建bean
public class Room {
public String door = null;
public String getDoor() {
return door;
}
public void setDoor(String door) {
this.door = door;
}
}
然后采用如下方法解析
//设置xml处理器
XStream xstream = new XStream();
//设置属性
xstream.alias( room ,Room.class);//把默认的testService1. Room转换成Room 或者在Room类上加 @XStreamAlias( Room )
xstream.processAnnotations(Room.class);//应用Room类的注解
xstream.autodetectAnnotations(true);//自动检测注解
xstream.alias( data ,ArrayList.class); //把跟节点看成一个list
xstream.ignoreUnknownElements();
xstream.alias( window ,NullPointerException.class);//把window节点指定为空
List itemlist = (List)xstream.fromXML(xml); //把xml转换成list
Room room = (Room)itemlist.get(0); //取得room节点
注:需要xml中结构顺序稳定,不能一会儿room在前面,一会儿window在前面。
4.xml节点层级复杂,但是只想解析其中的一部分内容
?xml version='1.0' encoding='UTF-8'?>
data>
room>
door>
id> /id>
/door>
/room>
window>
id>123 /id>
size>111 /size>
/window>
/data>
只解析door而不解析其他
public class Door {
public int id = 0;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
然后采用如下方法解析
//设置xml处理器
XStream xstream = new XStream();
//设置属性
xstream.alias( door ,Door.class);
xstream.processAnnotations(Door.class);//应用Door类的注解
xstream.autodetectAnnotations(true);//自动检测注解
xstream.alias( data ,ArrayList.class); //把跟节点看成一个list
xstream.ignoreUnknownElements();
xstream.alias( window ,NullPointerException.class);//把window节点指定为空
xstream.alias( room , ArrayList.class);
List itemlist = (List)xstream.fromXML(xml);//把xml转换成list
List roomlist = (List)itemlist.get(0);//取得room节点
Door door = (Door)roomlist.get(0);//取得door节点
注:需要xml中结构顺序稳定,不能一会儿room在前面,一会儿window在前面。
5.注意事项
1.对xml中所有节点都必须有处理方式,bean字段可以比xml中多,但是不能少。如:
(1)xstream.alias( data ,ArrayList.class);
(2)xstream.alias( window ,NullPointerException.class);
(3)在bean中解析。
2.用xstream把bean转xml时,转换后的内容不包括xml文件的头: ?xml version='1.0' encoding='UTF-8'?>,需要手动加。
3.xstream把bean转xml时,类名的节点会带包路径,如果不需要包路径,需要主动设置
xstream.alias( door ,Door.class);或者应用注解。
4.在bean中添加的注解,需要在应用时进行注册,如需要用Door中的注解,则需要进行设置:xstream.processAnnotations(Door.class);//应用Door类的注解
xstream.autodetectAnnotations(true);//自动检测注解