參考:https://www.yiibai.com/xstream/xstream_json.html
1.簡介:
XStream是一個簡單的基於Java庫,Java對象序列化到XML,反之亦然(即:可以輕易的將Java對象和xml文檔相互轉換)。
下載地址:http://x-stream.github.io/download.html
特點:
-
使用方便 - XStream的API提供了一個高層次外觀,以簡化常用的用例。
-
無需創建映射 - XStream的API提供了默認的映射大部分對象序列化。
-
性能 - XStream快速和低內存占用,適合於大對象圖或系統。
-
干凈的XML - XStream創建一個干凈和緊湊XML結果,這很容易閱讀。
-
不需要修改對象 - XStream可序列化的內部字段,如私有和最終字段,支持非公有制和內部類。默認構造函數不是強制性的要求。
-
完整對象圖支持 - XStream允許保持在對象模型中遇到的重復引用,並支持循環引用。
-
可自定義的轉換策略 - 定制策略可以允許特定類型的定制被表示為XML的注冊。
-
安全框架 - XStream提供了一個公平控制有關解組的類型,以防止操縱輸入安全問題。
-
錯誤消息 - 出現異常是由於格式不正確的XML時,XStream拋出一個統一的例外,提供了詳細的診斷,以解決這個問題。
-
另一種輸出格式 - XStream支持其它的輸出格式,如JSON。
2.API使用
0.使用的bean
User.java
package cn.qlq.bean; import java.util.Date; import java.util.List; public class User { private String name; private int age; private Date birthDay; private List<Group> groups; 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; } public Date getBirthDay() { return birthDay; } public void setBirthDay(Date birthDay) { this.birthDay = birthDay; } public User(String name, int age, Date birthDay) { super(); this.name = name; this.age = age; this.birthDay = birthDay; } public List<Group> getGroups() { return groups; } public void setGroups(List<Group> groups) { this.groups = groups; } @Override public String toString() { return "User [name=" + name + ", age=" + age + ", birthDay=" + birthDay + ", groups=" + groups + "]"; } }
Group.java
package cn.qlq.bean; import java.util.List; public class Group { private Integer id; private String name; private List<User> users; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Group(Integer id, String name) { super(); this.id = id; this.name = name; } public List<User> getUsers() { return users; } public void setUsers(List<User> users) { this.users = users; } @Override public String toString() { return "Group [id=" + id + ", name=" + name + ", users=" + users + "]"; } }
1.入門
package cn.qlq.test; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.util.ArrayList; import java.util.Date; import java.util.List; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.io.xml.StaxDriver; import cn.qlq.bean.Group; import cn.qlq.bean.User; public class XStreamtest { public static void main(String[] args) throws FileNotFoundException { // StaxDriver XStream xstream = new XStream(new StaxDriver()); // DomDriver // XStream xstream = new XStream(new DomDriver()); // JDomDriver // XStream xstream = new XStream(new JDomDriver()); // JsonHierarchicalStreamDriver // XStream xstream = new XStream(new JsonHierarchicalStreamDriver() { // public HierarchicalStreamWriter createWriter(Writer writer) { // return new JsonWriter(writer, JsonWriter.DROP_ROOT_MODE); // } // // }); // 構造bean User user = new User("zhangsan", 2, new Date()); List<Group> groups = new ArrayList<>(); groups.add(new Group(1, "g1")); groups.add(new Group(2, "g2")); user.setGroups(groups); // Object to XML Conversion String xml = xstream.toXML(user); System.out.println(xml); // XML String 轉bean User user2 = (User) xstream.fromXML(xml); System.out.println(user2); // 生成到xml文件 xstream.toXML(user, new FileOutputStream(new File("G:/user.xml"))); // 從xml文件讀取 User user3 = (User) xstream.fromXML(new File("G:/user.xml")); System.out.println(user3); } }
結果:
<?xml version='1.0' encoding='UTF-8'?><cn.qlq.bean.User><name>zhangsan</name><age>2</age><birthDay>2019-12-03 11:26:59.584 UTC</birthDay><groups><cn.qlq.bean.Group><id>1</id><name>g1</name></cn.qlq.bean.Group><cn.qlq.bean.Group><id>2</id><name>g2</name></cn.qlq.bean.Group></groups></cn.qlq.bean.User>
User [name=zhangsan, age=2, birthDay=Tue Dec 03 19:26:59 CST 2019, groups=[Group [id=1, name=g1, users=null], Group [id=2, name=g2, users=null]]]
User [name=zhangsan, age=2, birthDay=Tue Dec 03 19:26:59 CST 2019, groups=[Group [id=1, name=g1, users=null], Group [id=2, name=g2, users=null]]]
使用步驟:
(1)創建創建XStream對象。
XStream xstream = new XStream(new StaxDriver());
(2)序列化對象到XML
xstream.toXML(user);
(3)反序列化XML獲得對象。
xstream.fromXML(xml);
如果是DomDriver,序列化之后的xml如下:
<cn.qlq.bean.User> <name>zhangsan</name> <age>2</age> <birthDay>2019-12-03 11:30:44.703 UTC</birthDay> <groups> <cn.qlq.bean.Group> <id>1</id> <name>g1</name> </cn.qlq.bean.Group> <cn.qlq.bean.Group> <id>2</id> <name>g2</name> </cn.qlq.bean.Group> </groups> </cn.qlq.bean.User>
2.類混疊
用來創建一個類的XML完全限定名稱的別名
// 類混疊 xstream.alias("User", User.class); xstream.alias("Group", Group.class);
結果:
<User> <name>zhangsan</name> <age>2</age> <birthDay>2019-12-05 03:25:25.505 UTC</birthDay> <groups> <Group> <id>1</id> <name>g1</name> </Group> <Group> <id>2</id> <name>g2</name> </Group> </groups> </User>
3.字段混疊
字段混疊用於創建以XML字段的別名
// 字段混疊 xstream.aliasField("userName", User.class, "name"); xstream.aliasField("groupName", Group.class, "name");
結果:
<User> <userName>zhangsan</userName> <age>2</age> <birthDay>2019-12-05 03:27:42.700 UTC</birthDay> <groups> <Group> <id>1</id> <groupName>g1</groupName> </Group> <Group> <id>2</id> <groupName>g2</groupName> </Group> </groups> </User>
4.隱式集合混疊
// 隱式集合混疊 xstream.addImplicitCollection(User.class, "groups");
結果:
<User> <userName>zhangsan</userName> <age>2</age> <birthDay>2019-12-05 03:29:17.789 UTC</birthDay> <Group> <id>1</id> <groupName>g1</groupName> </Group> <Group> <id>2</id> <groupName>g2</groupName> </Group> </User>
5.屬性混疊
屬性混疊用於創建一個成員變量作為XML屬性序列化
// 屬性混疊 xstream.useAttributeFor(User.class, "name");
結果:
<cn.qlq.bean.User name="zhangsan"> <age>2</age> <birthDay>2019-12-05 10:23:20.309 UTC</birthDay> <groups> <cn.qlq.bean.Group> <id>1</id> <name>g1</name> </cn.qlq.bean.Group> <cn.qlq.bean.Group> <id>2</id> <name>g2</name> </cn.qlq.bean.Group> </groups> </cn.qlq.bean.User>
先屬性混疊,在字段混疊:
// 屬性混疊 xstream.useAttributeFor(User.class, "name"); // 字段混疊 xstream.aliasField("userName", User.class, "name");
結果:
<cn.qlq.bean.User userName="zhangsan"> <age>2</age> <birthDay>2019-12-05 10:25:16.901 UTC</birthDay> <groups> <cn.qlq.bean.Group> <id>1</id> <name>g1</name> </cn.qlq.bean.Group> <cn.qlq.bean.Group> <id>2</id> <name>g2</name> </cn.qlq.bean.Group> </groups> </cn.qlq.bean.User>
6. 包混疊
包裝混疊用於創建一個類XML的完全限定名稱的別名到一個新的限定名稱。
// 包混疊 xstream.aliasPackage("com", "cn.qlq");
結果:
<com.bean.User> <name>zhangsan</name> <age>2</age> <birthDay>2019-12-05 10:29:14.577 UTC</birthDay> <groups> <com.bean.Group> <id>1</id> <name>g1</name> </com.bean.Group> <com.bean.Group> <id>2</id> <name>g2</name> </com.bean.Group> </groups> </com.bean.User>
7.屬性忽略
可以忽略某些屬性不進行轉換
xstream.omitField(User.class, "birthDay");
結果:
<cn.qlq.bean.User> <name>zhangsan</name> <age>2</age> <groups> <cn.qlq.bean.Group> <id>1</id> <name>g1</name> </cn.qlq.bean.Group> <cn.qlq.bean.Group> <id>2</id> <name>g2</name> </cn.qlq.bean.Group> </groups> </cn.qlq.bean.User>
8.注解
XStream支持注解做同樣的任務
例如:
package cn.qlq.bean; import java.util.Date; import java.util.List; import com.thoughtworks.xstream.annotations.XStreamAlias; import com.thoughtworks.xstream.annotations.XStreamAsAttribute; import com.thoughtworks.xstream.annotations.XStreamImplicit; import com.thoughtworks.xstream.annotations.XStreamOmitField; @XStreamAlias("person") // 類混疊 public class User { @XStreamAlias("username") // 字段混疊 @XStreamAsAttribute // 字段作為屬性 private String name; @XStreamAlias("年齡") // 字段混疊 private int age; @XStreamOmitField // 忽略字段 private Date birthDay; @XStreamImplicit // 隱式集合混疊 private List<Group> groups; 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; } public Date getBirthDay() { return birthDay; } public void setBirthDay(Date birthDay) { this.birthDay = birthDay; } public User(String name, int age, Date birthDay) { super(); this.name = name; this.age = age; this.birthDay = birthDay; } public List<Group> getGroups() { return groups; } public void setGroups(List<Group> groups) { this.groups = groups; } @Override public String toString() { return "User [name=" + name + ", age=" + age + ", birthDay=" + birthDay + ", groups=" + groups + "]"; } }
還需要開啟掃描注解:
// 掃描注解 xstream.autodetectAnnotations(true);
結果:
<person username="zhangsan"> <年齡>2</年齡> <cn.qlq.bean.Group> <id>1</id> <name>g1</name> </cn.qlq.bean.Group> <cn.qlq.bean.Group> <id>2</id> <name>g2</name> </cn.qlq.bean.Group> </person>
9.XStream對象流
ObjectOutputStream objectOutputStream = xstream.createObjectOutputStream(new FileOutputStream("test.txt")); ObjectInputStream objectInputStream = xstream.createObjectInputStream(new FileInputStream("test.txt"));
例如:
package cn.qlq.test; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.ArrayList; import java.util.Date; import java.util.List; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.io.xml.StaxDriver; import cn.qlq.bean.Group; import cn.qlq.bean.User; public class XStreamtest { public static void main(String[] args) throws IOException, ClassNotFoundException { // StaxDriver XStream xstream = new XStream(new StaxDriver()); // DomDriver // XStream xstream = new XStream(new DomDriver()); // 掃描注解 xstream.autodetectAnnotations(true); ObjectOutputStream objectOutputStream = xstream.createObjectOutputStream(new FileOutputStream("G:/test.txt")); // 構造bean User user = new User("zhangsan", 2, new Date()); List<Group> groups = new ArrayList<>(); groups.add(new Group(1, "g1")); groups.add(new Group(2, "g2")); user.setGroups(groups); User user2 = new User("lisi", 3, new Date()); // 寫出到文件 objectOutputStream.writeObject(user); objectOutputStream.writeObject(user2); objectOutputStream.writeObject("Hello World"); objectOutputStream.close(); ObjectInputStream objectInputStream = xstream.createObjectInputStream(new FileInputStream("G:/test.txt")); User user3 = (User) objectInputStream.readObject(); User user4 = (User) objectInputStream.readObject(); System.out.println(user3); System.out.println(user4); } }
結果:
User [name=zhangsan, age=2, birthDay=null, groups=[Group [id=1, name=g1, users=null], Group [id=2, name=g2, users=null]]]
User [name=lisi, age=3, birthDay=null, groups=null]
查看G:/test.txt
<?xml version='1.0' encoding='UTF-8'?><object-stream><person username="zhangsan"><年齡>2</年齡><cn.qlq.bean.Group><id>1</id><name>g1</name></cn.qlq.bean.Group><cn.qlq.bean.Group><id>2</id><name>g2</name></cn.qlq.bean.Group></person><person username="lisi"><年齡>3</年齡></person><string>Hello World</string></object-stream>
10.自定義轉換器
-
canConvert - 檢查支持的對象類型的序列化。
-
marshal - 序列化對象到XML。
-
unmarshal - 從XML對象反序列化
package cn.qlq.bean; import java.text.ParseException; import java.text.SimpleDateFormat; import com.thoughtworks.xstream.converters.Converter; import com.thoughtworks.xstream.converters.MarshallingContext; import com.thoughtworks.xstream.converters.UnmarshallingContext; import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; public class UserConverter implements Converter { @Override public boolean canConvert(Class arg0) { return arg0.equals(User.class); } @Override public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext arg2) { User user = (User) value; writer.startNode("name"); writer.setValue(user.getName()); writer.endNode(); writer.startNode("出生日期"); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); writer.setValue(simpleDateFormat.format(user.getBirthDay())); writer.endNode(); } @Override public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext arg1) { User user = new User("", 0, null); while (reader.hasMoreChildren()) { // 讀取name reader.moveDown(); String nodeName = reader.getNodeName(); String nodeValue = reader.getValue(); if ("name".equals(nodeName)) { user.setName(nodeValue); } if ("出生日期".equals(nodeName)) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); try { user.setBirthDay(simpleDateFormat.parse(nodeValue)); } catch (ParseException e) { e.printStackTrace(); } } reader.moveUp(); } return user; } }
(2)注冊轉換器
xstream.registerConverter(new UserConverter());
測試:
package cn.qlq.test; import java.io.FileNotFoundException; import java.util.Date; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.io.xml.DomDriver; import cn.qlq.bean.User; import cn.qlq.bean.UserConverter; public class XStreamtest { public static void main(String[] args) throws FileNotFoundException { XStream xstream = new XStream(new DomDriver()); xstream.registerConverter(new UserConverter()); // 構造bean User user = new User("zhangsan", 2, new Date()); String xml = xstream.toXML(user); System.out.println(xml); User user2 = (User) xstream.fromXML(xml); System.out.println(user2); } }
結果:
<cn.qlq.bean.User>
<name>zhangsan</name>
<出生日期>2019-12-06</出生日期>
</cn.qlq.bean.User>
User [name=zhangsan, age=0, birthDay=Fri Dec 06 00:00:00 CST 2019, groups=null]
11.XStream編寫JSON
public static void main(String[] args) throws FileNotFoundException { XStream xstream = new XStream(new JsonHierarchicalStreamDriver() { public HierarchicalStreamWriter createWriter(Writer writer) { return new JsonWriter(writer, JsonWriter.DROP_ROOT_MODE); } }); xstream.registerConverter(new UserConverter()); // 構造bean User user = new User("zhangsan", 2, new Date()); String xml = xstream.toXML(user); System.out.println(xml); }
結果:
{ "name": "zhangsan", "出生日期": "2019-12-06" }