JavaDemo——使用XStream在java对象与xml之间转换

XStream是基于OXMapping技术,在xml和java对象之间序列化和反序列化的一个库,使用简单,对java对象要求少,没有共有私有或者构造方法上的要求,还支持json转化;

使用XStream需要maven引用:

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

使用JettisonMappedXmlDriver处理json需要maven引用:

        <dependency>
		    <groupId>org.codehaus.jettison</groupId>
		    <artifactId>jettison</artifactId>
		    <version>1.4.1</version>
		</dependency>

Demo1不使用注解:

/**
 * 2021年8月25日下午3:34:50
 */
package testXStream;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringReader;
import java.io.Writer;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamDriver;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver;
import com.thoughtworks.xstream.io.json.JsonHierarchicalStreamDriver;
import com.thoughtworks.xstream.io.json.JsonWriter;
import com.thoughtworks.xstream.io.xml.Dom4JDriver;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.thoughtworks.xstream.io.xml.StaxDriver;
import com.thoughtworks.xstream.persistence.FilePersistenceStrategy;
import com.thoughtworks.xstream.persistence.PersistenceStrategy;
import com.thoughtworks.xstream.persistence.XmlArrayList;
import com.thoughtworks.xstream.persistence.XmlMap;
import com.thoughtworks.xstream.persistence.XmlSet;
import com.thoughtworks.xstream.security.AnyTypePermission;

/**
 * @author XWF
 *
 */
public class TestXStream1 {
	
	public static int i = 1;
	
	@BeforeEach
	public void before() {
		System.out.println(String.format("--------------%d--------------", i++));
	}
	@AfterEach
	public void after() {
		System.out.println();
	}

	@Test
	public void test1() {
		Student stu1 = new Student(1, "Jack", 21);
		Student stu2 = new Student(2, "Tom", 22);
		School sch = new School();
		sch.schoolName = "HelloSchool";
		sch.students.add(stu1);
		sch.students.add(stu2);
//		XStream x = new XStream(new Dom4JDriver());
//		XStream x = new XStream(new DomDriver());
//		XStream x = new XStream(new StaxDriver());
		XStream x = new XStream();//默认XppDriver
		String str = x.toXML(sch);//obj转xml
		System.out.println(str);
		x.alias("SCHOOL", School.class);//给类起别名
		x.aliasPackage("X", "testXStream");//给包起别名
		x.aliasField("StuName", Student.class, "name");//给字段起别名
//		x.useAttributeFor(Student.class, "id");//将字段设置为属性
		x.aliasAttribute(Student.class, "id", "ID");//设置属性并起别名
		x.omitField(Student.class, "age");//忽略字段
		x.ignoreUnknownElements();//忽略未知元素
		String str2 = x.toXML(sch);
		System.out.println(str2);
		x.addPermission(AnyTypePermission.ANY);//设置许可,移除ForbiddenClassException异常
		School newSchool = (School) x.fromXML(str2);//xml转obj
		System.out.println(newSchool);
	}
	@Test
	public void test2() {
		Student stu1 = new Student(3, "Marry", 17);
		Student stu2 = new Student(4, "Jerry", 16);
		School sch = new School();
		sch.schoolName = "MySchool";
		sch.students.add(stu1);
		sch.students.add(stu2);
		XStream x = new XStream();
		System.out.println(x.toXML(sch));
//		x.alias("STU", Student.class);
		x.addImplicitCollection(School.class, "students", "NEWstudent", Student.class);//将集合的根节点隐藏
		String str = x.toXML(sch);
		System.out.println(str);
		x.addPermission(AnyTypePermission.ANY);
		System.out.println(x.fromXML(str));
	}
	@Test
	public void test3() {
		Student stu = new Student(5, "Jack", 20);
		XStream x = new XStream(new JettisonMappedXmlDriver());//序列化、反序列化json,需要引入jettison依赖
//		XStream x = new XStream(new JsonHierarchicalStreamDriver());//只能序列化json
		x.setMode(XStream.NO_REFERENCES);//禁用引用
		x.alias("STUDENT", Student.class);
		String str = x.toXML(stu);
		System.out.println(str);
		x.addPermission(AnyTypePermission.ANY);
		Student newStu = (Student) x.fromXML(str);
		System.out.println(newStu);
	}
	@Test
	public void test4() {
		Student stu = new Student(6, "John", 18);
		XStream x = new XStream(new JsonHierarchicalStreamDriver() {
			@Override
			public HierarchicalStreamWriter createWriter(Writer out) {
				return new JsonWriter(out, JsonWriter.DROP_ROOT_MODE);//去掉根节点
			}
		});
		String str = x.toXML(stu);
		System.out.println(str);
//		x.addPermission(AnyTypePermission.ANY);
//		Student newStu = (Student) x.fromXML(str);//无根节点无法反序列化,也不需使用JettisonMappedXmlDriver
//		System.out.println(newStu);
	}
	@Test
	public void test5() {
		Student stu = new Student(7, "Bill", 25);
		XStream x = new XStream();
		x.registerConverter(new MyConverter());//注册自定义转换器
		String str = x.toXML(stu);
		System.out.println(str);
		x.addPermission(AnyTypePermission.ANY);
		System.out.println(x.fromXML(str));
	}
	@Test
	public void test6() {
		Student stu = new Student(8, "James", 24);
		XStream x = new XStream();
		//默认根节点object-stream,也可以通过createObjectOutputStream第二个参数设置
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		try (ObjectOutputStream oos = x.createObjectOutputStream(bos)) {
			oos.writeObject(stu);
			oos.writeBoolean(true);
			oos.writeInt(100);
		} catch (IOException e) {
			e.printStackTrace();
		}
		byte[] byteArray = bos.toByteArray();
		System.out.println(new String(byteArray));
		
		String str = "<root>"
				+ "<STU><id>9</id><name>Mark</name><age>16</age></STU>"
				+ "<boolean>false</boolean>"
				+ "</root>";
		try (ObjectInputStream ois = x.createObjectInputStream(new StringReader(str))) {
			x.alias("STU", Student.class);
			x.addPermission(AnyTypePermission.ANY);
			Student readStu = (Student) ois.readObject();
			System.out.println(readStu);
			boolean b = ois.readBoolean();
			System.out.println(b);
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	@Test
	public void test7() {
		XStream x = new XStream();
		File baseDirectory = new File("./src/testXStream/list/");
		if (!baseDirectory.exists()) {
			baseDirectory.mkdir();
		}
		PersistenceStrategy strategy = new FilePersistenceStrategy(baseDirectory, x);
		//写到xml文件里
		//(XmlArrayList,XmlMap,XmlSet不要写到同一个文件夹下,否则读取的时候it.hasNext永远为true并且后面的it.next为null)
		System.out.println("XmlArrayList");
		XmlArrayList list = new XmlArrayList(strategy);
		list.add(new Student(10, "AAA", 21));//int@0.xml
		list.add(new Student(11, "BBB", 22));
		list.add(new Student(12, "CCC", 23));
		
		File f2 = new File("./src/testXStream/map/");
		if (!f2.exists()) {
			f2.mkdir();
		}
		x.addPermission(AnyTypePermission.ANY);//XmlSet,XmlMap在添加的时候可能会用到反序列化校验
		PersistenceStrategy strategy2 = new FilePersistenceStrategy(f2, x);
		System.out.println("XmlMap");
		XmlMap map = new XmlMap(strategy2);
		map.put("A", new Student(13, "DDDD", 24));//string@A.xml
		map.put("B", new Student(14, "EEEE", 25));
		
		File f3 = new File("./src/testXStream/set/");
		if (!f3.exists()) {
			f3.mkdir();
		}
		PersistenceStrategy strategy3 = new FilePersistenceStrategy(f3, x);
		System.out.println("XmlSet");
		XmlSet set = new XmlSet(strategy3);
		set.add(new Student(15, "FF", 26));//long@xxxxxxxxxxxxx.xml
		set.add(new Student(16, "GG", 27));
	}
	@Test
	public void test8() {
		XStream x = new XStream();
		x.addPermission(AnyTypePermission.ANY);
		File f1 = new File("./src/testXStream/list/");
		PersistenceStrategy strategy = new FilePersistenceStrategy(f1, x);
		//读取xml文件
		XmlArrayList list = new XmlArrayList(strategy);
		Iterator<Student> it = list.iterator();
		while (it.hasNext()) {
			System.out.println("list->" + it.next());
			it.remove();//删除文件
		}
		
		File f2 = new File("./src/testXStream/map/");
		PersistenceStrategy strategy2 = new FilePersistenceStrategy(f2, x);
		XmlMap map = new XmlMap(strategy2);
		for(Object k : map.keySet()) {
			System.out.println("map->key:" + k + " val:" + map.get(k));
			map.remove(k);//删除
		}
		
		File f3 = new File("./src/testXStream/set/");
		PersistenceStrategy strategy3 = new FilePersistenceStrategy(f3, x);
		XmlSet set = new XmlSet(strategy3);
		Iterator<Student> it2 = set.iterator();
		while (it2.hasNext()) {
			System.out.println("set->" + it2.next());
			it2.remove();//删除
		}
		
		f1.delete();//删除空文件夹
		f2.delete();
		f3.delete();
	}
}

class Student {
	public int id;
	public String name;
	public int age;
	public Student(int id, String name, int age) {
		super();
		this.id = id;
		this.name = name;
		this.age = age;
	}
	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";
	}
}
class School {
	public String schoolName;
	public List<Student> students = new ArrayList<>();
	@Override
	public String toString() {
		return "School [schoolName=" + schoolName + ", students=" + students + "]";
	}
}
class MyConverter implements Converter {
	@Override
	public boolean canConvert(Class type) {
		System.out.println("--准备判断类型");
		return type.equals(Student.class);//判断可转换的数据类型
	}
	@Override
	public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
		//序列化为xml/json
		System.out.println("--准备序列化");
		Student stu = (Student) source;
		writer.addAttribute("ID", stu.id + "");
		writer.startNode("StuId");
		writer.setValue(stu.id + "");
		writer.endNode();
		writer.startNode("StuName");
		writer.addAttribute("age", stu.age + "");
		writer.setValue(stu.name);
		writer.endNode();
		writer.startNode("StuAge");
		writer.setValue(stu.age + "");
		writer.endNode();
	}
	@Override
	public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
		//反序列化为obj
		System.out.println("--准备反序列化");
		int sId = -1;
		String sName = "";
		int sAge = -1;
		System.out.println("--Attribute:" + reader.getAttributeName(0) + reader.getAttribute(0));
		reader.moveDown();//选择当前子节点作为当前节点,跟moveUp对应调用
		sId = Integer.parseInt(reader.getValue());
		reader.moveUp();//选择父节点作为当前节点
		reader.moveDown();
		System.out.println("sName attribute:age=" + reader.getAttribute("age"));//需要在getValue前(读取value节点前的开始节点才有属性)
		sName = reader.getValue();
		reader.moveUp();
		reader.moveDown();
		sAge = Integer.parseInt(reader.getValue());
		reader.moveUp();
		return new Student(sId, sName, sAge);
	}
}

运行结果:

 

 执行test7(执行test8之前)生成的xml文件:

实例化XStream的Driver参数有:

Demo2使用标签:

/**
 * 2021年8月25日下午3:35:27
 */
package testXStream;

import java.util.ArrayList;
import java.util.List;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import com.thoughtworks.xstream.annotations.XStreamImplicit;
import com.thoughtworks.xstream.annotations.XStreamOmitField;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.SingleValueConverter;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.converters.basic.BooleanConverter;
import com.thoughtworks.xstream.converters.basic.IntConverter;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver;
import com.thoughtworks.xstream.security.AnyTypePermission;

/**
 * @author XWF
 *
 */
public class TestXStream2 {

	public static int i = 1;
	
	@BeforeEach
	public void before() {
		System.out.println(String.format("================ %d ================", i++));
	}
	@AfterEach
	public void after() {
		System.out.println();
	}

	@Test
	public void test1() {
		Book b1 = new Book("10001", "BookA", 30.3d);
		Book b2 = new Book("10002", "BookB", 100.1d);
		Library lib = new Library();
		lib.name = "MyLibrary";
		lib.books.add(b1);
		lib.books.add(b2);
		XStream x = new XStream();
		x.processAnnotations(Book.class);//设置应用注解的类
		x.processAnnotations(Library.class);
		String str = x.toXML(lib);
		System.out.println(str);
		x.addPermission(AnyTypePermission.ANY);
		System.out.println(x.fromXML(str));
	}
	@Test
	public void test2() {
		Book b1 = new Book("10001", "BookA", 30.3d);
		Book b2 = new Book("10002", "BookB", 100.1d);
		Library lib = new Library();
		lib.name = "MyLibrary";
		lib.books.add(b1);
		lib.books.add(b2);
		XStream x = new XStream(new JettisonMappedXmlDriver());
		x.processAnnotations(new Class[] {Book.class, Library.class});//设置应用注解的类
		x.addPermission(AnyTypePermission.ANY);
		String str = x.toXML(lib);
		System.out.println(str);
		System.out.println(x.fromXML(str));
	}
	@Test
	public void test3() {
		A aObj = new A();
		aObj.a = "AAAA";
		aObj.b = 10;
		aObj.c = true;
		B b = new B("dddddd", -12);
		aObj.bObj = b;
		aObj.bObj2 = b;//跟aObj.bObj引用同一对象
		XStream x = new XStream();
		x.autodetectAnnotations(true);//自动检测注解
		x.addPermission(AnyTypePermission.ANY);
		x.setMode(XStream.NO_REFERENCES);//禁止aObj.bObj2使用引用,否则会序列化为<bObj2 reference="../BCls"/>
		String str = x.toXML(aObj);
		System.out.println(str);
		System.out.println(x.fromXML(str));
	}
}
@XStreamAlias("BOOK")	//别名
class Book {
	@XStreamAsAttribute()	//设置为属性
	@XStreamAlias("BookNo")	//别名
	public String no;
	public String name;
	public double price;
	@XStreamOmitField	//忽略字段
	public String temp = "xxx";
	public Book(String no, String name, double price) {
		super();
		this.no = no;
		this.name = name;
		this.price = price;
	}
	@Override
	public String toString() {
		return "Book [no=" + no + ", name=" + name + ", price=" + price + "]";
	}
}
@XStreamAlias("LIBRARY")
class Library {
	public String name;
	@XStreamImplicit(itemFieldName = "MyBook")	//隐藏集合根节点books,itemFieldName设置下面子节点别名
	public List<Book> books = new ArrayList<>();
	@Override
	public String toString() {
		return "Library [name=" + name + ", books=" + books + "]";
	}
}
@XStreamAlias("ACls")
class A {
	public String a;
	public int b;
	@XStreamConverter(value = BooleanConverter.class, booleans = {false}, strings = {"yes", "no"})
	public boolean c;
	@XStreamAlias("BCls")
	@XStreamConverter(BConverter.class)//需要为public class
	public B bObj;
	@XStreamConverter(BConverter2.class)
	public B bObj2;
	@Override
	public String toString() {
		return "A [a=" + a + ", b=" + b + ", c=" + c + ", bObj=" + bObj + ", bObj2=" + bObj2 + "]";
	}
}
class B {
	public String d;
	public int e;
	public B(String d, int e) {
		super();
		this.d = d;
		this.e = e;
	}
	@Override
	public String toString() {
		return "B [d=" + d + ", e=" + e + "]";
	}
}

 BConverter.java

/**
 * 2021年8月27日上午10:21:21
 */
package testXStream;

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;

/**
 * @author XWF
 *
 */
public class BConverter implements Converter {

	@Override
	public boolean canConvert(Class type) {
		return type.equals(B.class);
	}

	@Override
	public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
		B b = (B) source;
		writer.setValue(b.d + "_" + b.e);
	}

	@Override
	public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
		String str = reader.getValue();
		String[] s = str.split("_");
		String bd = s[0];
		int be = Integer.parseInt(s[1]);
		return new B(bd, be);
	}
}

 BConverter2.java

/**
 * 2021年8月27日上午10:28:04
 */
package testXStream;

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;

/**
 * @author XWF
 *
 */
public class BConverter2 implements Converter {

	@Override
	public boolean canConvert(Class type) {
		return type.equals(B.class);
	}

	@Override
	public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
		B b = (B) source;
		writer.startNode("BD");
		writer.setValue(b.d);
		writer.endNode();
		writer.startNode("BE");
		writer.setValue(b.e + "");
		writer.endNode();
	}

	@Override
	public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
		reader.moveDown();
		String bd = reader.getValue();
		reader.moveUp();
		reader.moveDown();
		int be = Integer.parseInt(reader.getValue());
		reader.moveUp();
		return new B(bd, be);
	}

}

 运行结果:

需要注意的地方:

1.反序列化的时候有未知标签需使用ignoreUnknownElements()忽略;

2.反序列化的时候通常需要addPermission(AnyTypePermission.ANY);

3.JettisonMappedXmlDriver支持序列化和反序列化,需要引入jettison包,JsonHierarchicalStreamDriver只能序列化;

4.无根节点的json反序列化会失败;

5.使用XmlArrayList、XmlMap、XmlSet生成xml文件的时候,最好生成到不同目录,在生成的时候需要addPermission(AnyTypePermission.ANY);

6.使用注解的时候需要使用processAnnotations()或者autodetectAnnotations(true);

7.使用@XStreamConverter指定转换器的时候,自定义转换器类需要是public class(而使用registerConverter()方法指定的时候可以不用public);

8.字段有相同引用的时候可以用setMode(XStream.NO_REFERENCES)禁用引用;

9.自定义转换器反序列化方法里获得属性getAttribute()方法的位置需要在开始标签的位置;

 

 

 

参考:

http://x-stream.github.io/

https://blog.csdn.net/qq_21909121/article/details/51283465

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值