• 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.隐式集合混叠

      隐式集合混叠时使用的集合是表示在XML无需显示根。例如,在我们的例子中,我们需要一个接一个,但不是在根节点来显示每一个节点。
            // 隐式集合混叠
            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对象流

      XStream提供java.io.ObjectInputStream和java.io.ObjectOutputStream替代实现,使对象流可以被序列化或XML序列化。当大对象集要被处理,保持在存储器中的一个对象,这是特别有用的。
    语法:
    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.自定义转换器 

    XStream允许从无到有写入转换器,这样开发人员可以编写一个完全新的实现,如何对象序列化到XML,反之亦然。 转换器接口提供了三种方法。
    • canConvert - 检查支持的对象类型的序列化。

    • marshal - 序列化对象到XML。

    • unmarshal - 从XML对象反序列化

    例如:

    (1)编写转换器
    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

    XStream支持JSON通过初始化XStream对象适当的驱动程序。 XStream目前支持JettisonMappedXmlDriver和JsonHierarchicalStreamDriver。
        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"
    }
  • 相关阅读:
    图与链表的深拷贝
    Codeforces Round #686(Div.3) [C- Sequence
    前缀和
    递归改非递归
    STL源码剖析笔记
    第六章 进程
    C++ 设计模式--模板模式、策略模式、观察者模式
    宏定义方式 进行枚举类型和枚举类型的相互转换
    Linux常见信号介绍
    git rebase 操作
  • 原文地址:https://www.cnblogs.com/qlqwjy/p/11978608.html
Copyright © 2020-2023  润新知