Java中如何使用XStream在java对象与xml之间互相转换呢?
下文笔者讲述java对象和xml之间互相转换的方法及示例分享,如下所示
使用注解的方式对Java对象和xml进行转换
Java和xml之间互相转换的实现思路
我们可以借助XStream对java对象和xml相关转换 XStream的使用思路: 1.引入相应依赖 2.编写代码或使用注解,即可实现Java对象和xml之间互相转换例:XStream相关依赖引入
使用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>例:硬编码
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; 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); } }
使用注解的方式对Java对象和xml进行转换
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;
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
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;
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
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;
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);
}
}
XStream之Java对象和xml转换注意事项
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()方法的位置需要在开始标签的位置;
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。


