文章目录
简介
XStream is a simple library to serialize objects to XML and back again.
依赖
XStream使用了XML解析器xpp3_min
<!-- https://mvnrepository.com/artifact/com.thoughtworks.xstream/xstream -->
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/xpp3/xpp3_min -->
<dependency>
<groupId>xpp3</groupId>
<artifactId>xpp3_min</artifactId>
<version>1.1.4c</version>
</dependency>
基础使用demo
以下分析均采用此demo
JavaBean对象
写两个JavaBean
package demo;
public class Score {
private String subject;
private int point;
public Score(String subject, int point) {
this.subject = subject;
this.point = point;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public int getPoint() {
return point;
}
public void setPoint(int point) {
this.point = point;
}
}
package demo;
import java.util.ArrayList;
import java.util.List;
public class Student {
private String name;
private String id;
private List<Score> scores = new ArrayList<Score>();
public Student(String name, String id) {
this.name = name;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Score> getScores() {
return scores;
}
public void setScores(List<Score> scores) {
this.scores = scores;
}
public void addScore(Score score){
scores.add(score);
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
代码
package demo;
import com.thoughtworks.xstream.XStream;
public class Demo {
public static void main(String[] args) {
Score math = new Score("math", 99);
Student student = new Student("Bob", "114514");
student.addScore(math);
XStream xStream = new XStream();
// 序列化
String string = xStream.toXML(student);
System.out.println(string);
// 反序列化
Student student1 = (Student) xStream.fromXML(string);
System.out.println(student1.toString()+ " " +student1.getName() + " " +student1.getScores().get(0).getSubject());
}
}
序列化结果
<demo.Student>
<name>Bob</name>
<id>114514</id>
<scores>
<demo.Score>
<subject>math</subject>
<point>99</point>
</demo.Score>
</scores>
</demo.Student>
反序列化结果
demo.Student@5f9d02cb Bob math
同一对象序列化和反序列化的一致性
对于相同XStream,反复序列化和反序列化同一个对象,结果都是一致的
XStream xStream = new XStream();
String string = xStream.toXML(student);
System.out.println(string);
Student student1 = (Student) xStream.fromXML(string);
String string1 = xStream.toXML(student1);
System.out.println(string.equals(string1));
进阶操作
给标签起别名
XStream xStream = new XStream();
xStream.alias("StuInfo", Student.class);
String string = xStream.toXML(student);
将对象属性转化为XML标签属性
XStream xStream = new XStream();
xStream.useAttributeFor(Student.class, "name");
xStream.useAttributeFor(Student.class, "id");
String string = xStream.toXML(student);
添加隐式集合
对于集合的序列化和反序列化,告知XStream核心能够简化操作
XStream xStream = new XStream();
xStream.addImplicitCollection(Student.class, "scores");xStream.useAttributeFor(Student.class, "name");
String string = xStream.toXML(student);
实际体现就是:给demo对象再添加一个score
此时List<Score>的标签就被自动忽略了,正常应该是<scores> <demo.Score></demo.Score>... </scores>
同样的反序列化时候直接多条<demo.Score>
合并写入即可,XStream核心已经知晓此处是一个隐式的集合
如果没有事先声明此处是隐式集合,只把多条集合元素合并写入会抛错
设置变量不被序列化
XStream xStream = new XStream();
xStream.omitField(Student.class, "scores");
String string = xStream.toXML(student);
XStream核心结构图
浅析XStream序列化操作源码
调用toXML()
时,首先new了一个StringWriter作为输出
之后这个StringWriter转换成了一个PrettyPrintWriter用于优化分层结构的XML输出,然后进入marshal方法
传入convertLookup和mapper
接下来就是新建树编组器,然后开始编组
首先进行头节点也就是整个类最外层的XML编组,然后convertAnother方法开始转换对象
来到doMarshal()
,首先调用反射获取属性
然后放到List中
如果涉及可迭代对象,对内部有处理,流程也是调用marshal()到convertAnother()到visitSerializableFields()
层次化体现在使用栈和路径的概念来处理包含关系
回到doMarshal()
,当所有属性都添加到fields中,就开始写入writer了,一个迭代器循环
调用writeField序列化属性,这里传入了五个参数:属性名称、别名、类型、所属类、值
首先写入左边的XML标签
然后调用marshallField写入值,最后再写入右XML标签
写入值时单独提取了出来,也就是说无论是键还是值,序列化操作都是提取成item转换,只是在标签左右尖括号等处有特殊额外写入处理
写入值最终调用了PrettyPrintWriter.setValue
浅析XStream反序列化操作源码
反序列化的流程大概与序列化一致
调用MarshallingStrategy.unmarshal
解组
首先调用HierarchicalStreams.readClassType
获取反序列化的类,然后调用convertAnother进行复原
获取converter转换器,进去看看细节
对于普通Bean,默认是ReflectionConverter,从缓存中获取的;如果缓存没有下面就会查找合适的converter
有很多个converter
值得注意的是,有两个特殊converter:一般Bean是反射converter,而实现了serializable接口的类走的是serializableConverter
serializableConverter的介绍:看介绍是可以调用readObject方法模拟正常反序列化流程
往后来到AbstractReflectionConverter.unmarshal
,调用instantiateNewInstance
新建反序列化类的实例,然后调用doUnmarshal
给它添加所有的属性参数
参考
https://x-stream.github.io/index.html
https://github.com/jakingting/Xtream-jar/tree/master/XStreamUML
https://blog.csdn.net/u014565127/article/details/104419528
https://www.jianshu.com/p/387c568faf62
完
欢迎关注我的CSDN博客 :@Ho1aAs
版权属于:Ho1aAs
本文链接:https://ho1aas.blog.csdn.net/article/details/126250860
版权声明:本文为原创,转载时须注明出处及本声明