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()方法的位置需要在开始标签的位置;
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。