XStream处理XML用法
参考: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" }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2017-12-03 Java配置方式读取外部的资源配置文件
2017-12-03 Spring的Java配置方式
2017-12-03 JVM即时编译(JIT)
2017-12-03 B树、B-树、B+树、B*树介绍,和B+树更适合做文件索引的原因
2017-12-03 MySQL存储引擎之Myisam和Innodb总结性梳理