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"
}

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM