XStream學習手冊

一、前言

1、XStream官網

    //x-stream.github.io

2、XStream是什麼

    XStream是一個簡單的基於Java的類庫,用來將Java對象序列化成XML(JSON)或反序列化為對象(即:可以輕易的將Java對象和XML文檔相互轉換)

3、XSteam能幹什麼

    XStream在運行時使用Java反射機制對要進行序列化的對象樹的結構進行探索,並不需要對對象作出修改。XStream可以序列化內部欄位,包括私private和final欄位,並且支援非公開類以及內部類。

    在預設情況下,XStream不需要配置映射關係,對象和欄位將映射為同名XML元素。但是當對象和欄位名與XML中的元素名不同時,XStream支援指定別名。XStream支援以方法調用的方式,或是Java 標註的方式指定別名。

    XStream在進行數據類型轉換時,使用系統預設的類型轉換器。同時,也支援用戶自定義的類型轉換器。

4、XStream特點

  • 使用方便 – XStream的API提供了一個高層次外觀,以簡化常用的用例

  • 無需創建映射 – XStream的API提供了默認的映射大部分對象序列化

  • 性能  – XStream快速和低記憶體佔用,適合於大對象圖或系統

  • 乾淨的XML  – XStream創建一個乾淨和緊湊XML結果,這很容易閱讀

  • 不需要修改對象 – XStream可序列化的內部欄位,如private和final欄位,支援非公開類和內部類。默認構造函數不是強制性的要求

  • 完整對象圖支援 – XStream允許保持在對象模型中遇到的重複引用,並支援循環引用

  • 可自定義的轉換策略 – 訂製策略可以允許特定類型的訂製被表示為XML的註冊

  • 安全框架 – XStream提供了一個公平控制有關解組的類型,以防止操縱輸入安全問題

  • 錯誤消息 – 出現異常是由於格式不正確的XML時,XStream拋出一個統一的例外,提供了詳細的診斷,以解決這個問題

  • 另一種輸出格式 – XStream支援其它的輸出格式,如JSON

5、XStream常見的用途

    傳輸、持久化、配置、單元測試

二、XStream入門

1、添加XSteam依賴

<dependency>
    <groupId>com.thoughtworks.xstream</groupId>
    <artifactId>xstream</artifactId>
    <version>1.4.12</version>
</dependency>
 <dependency>
    <groupId>org.codehaus.jettison</groupId>
    <artifactId>jettison</artifactId>
    <version>1.4.1</version>
</dependency>

2、XStream基本使用

package io.github.xstream.test01;
​
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver;
import lombok.AllArgsConstructor;
import lombok.ToString;
​
public class XStreamTest01 {
    public static void main(String[] args) {
        Student student = new Student("張三", 20);
        XStream xStream = new XStream();//需要XPP3庫
        //XStream xStream = new XStream(new DomDriver());//不需要XPP3庫
        //XStream xStream = new XStream(new StaxDriver());//不需要XPP3庫開始使用Java 6
        //XML序列化
        String xml = xStream.toXML(student);
        System.out.println(xml);
        //XML反序列化
        student = (Student) xStream.fromXML(xml);
        System.out.println(student);
​
        xStream = new XStream(new JettisonMappedXmlDriver());
        xStream.setMode(XStream.NO_REFERENCES);
        //Json序列化
        String json = xStream.toXML(student);
        System.out.println(json);
        //Json反序列
        student = (Student) xStream.fromXML(json);
        System.out.println(student);
    }
}
​
@AllArgsConstructor
@ToString
class Student {
    private String name;
    private int age;
}

3、程式運行結果

<io.github.xstream.test01.Student>
  <name>張三</name>
  <age>20</age>
</io.github.xstream.test01.Student>
Security framework of XStream not initialized, XStream is probably vulnerable.
Student(name=張三, age=20)
{"io.github.xstream.test01.Student":{"name":"張三","age":20}}
Student(name=張三, age=20)
Security framework of XStream not initialized, XStream is probably vulnerable.

注意:文中使用到的Lombok註解,Lombok依賴自行添加;XStream序列化XML時需要引用的jar包:xstream-[version].jar、xpp3-[version].jar、xmlpull-[version].jar,當引入xstream依賴後會自動依賴xpp3、xmlpull依賴。XStream序列化JSON需要引用的jar包:jettison-[version].jar。

    使用XStream序列化時,對JavaBean沒有任何限制。JavaBean的欄位可以是私有的,也可以沒有getter或setter方法,還可以沒有默認的構造函數。

    XStream序列化XML時可以允許用戶使用不同的XML解析器,用戶可以使用一個標準的JAXP DOM解析器或自Java 6集成STAX解析器。這樣用戶就不需要依賴xpp3-[version].jar。

三、XStream混疊

1、混疊是一種技術來訂製生成XML或者使用XStream特定的格式化XML。假設,一個下面的XML格式是用於序列化/反序列化Student對象。

<student name="張三">
    <phone>
        <brand>小米</brand>
        <description>小米手機的描述</description>
    </phone>
    <phone>
        <brand>蘋果</brand>
        <description>蘋果手機的描述</description>
    </phone>
</student>

2、根椐上面的XML格式,我們創建實體類

@AllArgsConstructor
@ToString
class Student {
    private String studentName;
    private List<Phone> phones;
}
​
@AllArgsConstructor
@ToString
class Phone {
    private String brand;
    private String description;
}

3、執行程式碼

package io.github.xstream.test02;
​
import com.thoughtworks.xstream.XStream;
import lombok.AllArgsConstructor;
import lombok.ToString;
​
import java.util.ArrayList;
import java.util.List;
​
public class XStreamTest02 {
    public static void main(String[] args) {
        List<Phone> phones = new ArrayList<>();
        phones.add(new Phone("小米手機", "小米手機的描述"));
        phones.add(new Phone("蘋果手機", "蘋果手機的描述"));
        Student student = new Student("張三", phones);
​
        XStream xStream = new XStream();//需要XPP3庫
        //XML序列化
        String xml = xStream.toXML(student);
        System.out.println(xml);
    }
}
​
@AllArgsConstructor
@ToString
class Student {
    private String studentName;
    private List<Phone> phones;
}
​
@AllArgsConstructor
@ToString
class Phone {
    private String brand;
    private String description;
}

4、驗證輸出

<io.github.xstream.test02.Student>
  <studentName>張三</studentName>
  <phones>
    <io.github.xstream.test02.Phone>
      <brand>小米手機</brand>
      <description>小米手機的描述</description>
    </io.github.xstream.test02.Phone>
    <io.github.xstream.test02.Phone>
      <brand>蘋果手機</brand>
      <description>蘋果手機的描述</description>
    </io.github.xstream.test02.Phone>
  </phones>
</io.github.xstream.test02.Student>

    在上面的結果,我們已經看到了Student對象名稱是完全合格的。要替換它作為學生的標籤,按照四、XStream類混疊的步驟

    另外,在上述結果中可以看出,所需studentName要重命名來命名。要替換它,按照五、XStream欄位混疊的步驟

    在上面的結果,我們可以看到手機標記被添加成為手機列表。替換它,按照六、XStream隱式集合混疊的步驟

    在上面的結果,我們可以看到這個名字來作為一個子節點,需要將它作為根節點的屬性。替換它,按照七、XStream屬性混疊的步驟

四、XStream類混疊

1、類混疊是用來創建一個類的XML完全限定名稱的別名。讓我們修改XStreamTest02例子,將下面的程式碼添加到XStreamTest02例子裡面

xStream.alias("student", Person02.class);
xStream.alias("phone", Phone.class);

2、執行程式碼

package io.github.xstream.test02;
​
import com.thoughtworks.xstream.XStream;
import lombok.AllArgsConstructor;
import lombok.ToString;
​
import java.util.ArrayList;
import java.util.List;
​
public class XStreamTest02 {
    public static void main(String[] args) {
        List<Phone> phones = new ArrayList<>();
        phones.add(new Phone("小米手機", "小米手機的描述"));
        phones.add(new Phone("蘋果手機", "蘋果手機的描述"));
        Student student = new Student("張三", phones);
​
        XStream xStream = new XStream();//需要XPP3庫
        xStream.alias("student", Student.class);
        xStream.alias("phone", Phone.class);
​
        //XML序列化
        String xml = xStream.toXML(student);
        System.out.println(xml);
    }
}
​
@AllArgsConstructor
@ToString
class Student {
    private String studentName;
    private List<Phone> phones;
}
​
@AllArgsConstructor
@ToString
class Phone {
    private String brand;
    private String description;
}

3、執行結果

<student>
  <studentName>張三</studentName>
  <phones>
    <phone>
      <brand>小米手機</brand>
      <description>小米手機的描述</description>
    </phone>
    <phone>
      <brand>蘋果手機</brand>
      <description>蘋果手機的描述</description>
    </phone>
  </phones>
</student>

可以看到<io.github.xstream.test02.Student>和<io.github.xstream.test02.Phone>分別被修改為了<student>和<phone>

五、XStream欄位混疊

1、欄位混疊用於創建以XML欄位的別名。讓我們再次修改原來的XStreamTest02例子,將下面的程式碼添加到XStreamTest02例子裡面

xStream.aliasField("name", Student.class, "studentName");

2、執行程式碼

package io.github.xstream.test02;
​
import com.thoughtworks.xstream.XStream;
import lombok.AllArgsConstructor;
import lombok.ToString;
​
import java.util.ArrayList;
import java.util.List;
​
public class XStreamTest02 {
    public static void main(String[] args) {
        List<Phone> phones = new ArrayList<>();
        phones.add(new Phone("小米手機", "小米手機的描述"));
        phones.add(new Phone("蘋果手機", "蘋果手機的描述"));
        Student student = new Student("張三", phones);
​
        XStream xStream = new XStream();//需要XPP3庫
        xStream.alias("student", Student.class);
        xStream.alias("phone", Phone.class);
        xStream.aliasField("name", Student.class, "studentName");
​
        //XML序列化
        String xml = xStream.toXML(student);
        System.out.println(xml);
    }
}
​
@AllArgsConstructor
@ToString
class Student {
    private String studentName;
    private List<Phone> phones;
}
​
@AllArgsConstructor
@ToString
class Phone {
    private String brand;
    private String description;
}

3、執行結果

<student>
  <name>張三</name>
  <phones>
    <phone>
      <brand>小米手機</brand>
      <description>小米手機的描述</description>
    </phone>
    <phone>
      <brand>蘋果手機</brand>
      <description>蘋果手機的描述</description>
    </phone>
  </phones>
</student>

可以看到<studentName>被修改為了<name>

六、XStream隱式集合混疊

1、隱式集合混疊時使用的集合是表示在XML無需顯示根。例如,在我們的例子中,我們需要一個接一個,但不是在根節點來顯示每一個節點。讓我們再次修改原來的XStreamTest02例子,將下面的程式碼添加到XStreamTest02例子裡面

xStream.addImplicitCollection(Student.class, "phones");

2、執行程式碼

package io.github.xstream.test02;
​
import com.thoughtworks.xstream.XStream;
import lombok.AllArgsConstructor;
import lombok.ToString;
​
import java.util.ArrayList;
import java.util.List;
​
public class XStreamTest02 {
    public static void main(String[] args) {
        List<Phone> phones = new ArrayList<>();
        phones.add(new Phone("小米手機", "小米手機的描述"));
        phones.add(new Phone("蘋果手機", "蘋果手機的描述"));
        Student student = new Student("張三", phones);
​
        XStream xStream = new XStream();//需要XPP3庫
        xStream.alias("student", Student.class);
        xStream.alias("phone", Phone.class);
        xStream.aliasField("name", Student.class, "studentName");
        xStream.addImplicitCollection(Student.class, "phones");
​
        //XML序列化
        String xml = xStream.toXML(student);
        System.out.println(xml);
    }
}
​
@AllArgsConstructor
@ToString
class Student {
    private String studentName;
    private List<Phone> phones;
}
​
@AllArgsConstructor
@ToString
class Phone {
    private String brand;
    private String description;
}

3、執行結果

<student>
  <name>張三</name>
  <phone>
    <brand>小米手機</brand>
    <description>小米手機的描述</description>
  </phone>
  <phone>
    <brand>蘋果手機</brand>
    <description>蘋果手機的描述</description>
  </phone>
</student>

可以看到<phones>被隱藏了

七、XStream屬性混疊

1、屬性混疊用於創建一個成員變數作為XML屬性序列化。讓我們再次修改原來的XStreamTest02例子,將下面的程式碼添加到XStreamTest02例子裡面

xStream.useAttributeFor(Student.class, "studentName");

2、執行程式碼

package io.github.xstream.test02;
​
import com.thoughtworks.xstream.XStream;
import lombok.AllArgsConstructor;
import lombok.ToString;
​
import java.util.ArrayList;
import java.util.List;
​
public class XStreamTest02 {
    public static void main(String[] args) {
        List<Phone> phones = new ArrayList<>();
        phones.add(new Phone("小米手機", "小米手機的描述"));
        phones.add(new Phone("蘋果手機", "蘋果手機的描述"));
        Student student = new Student("張三", phones);
​
        XStream xStream = new XStream();//需要XPP3庫
        xStream.alias("student", Student.class);
        xStream.alias("phone", Phone.class);
        xStream.aliasField("name", Student.class, "studentName");
        xStream.addImplicitCollection(Student.class, "phones");
        xStream.useAttributeFor(Student.class, "studentName");
​
        //XML序列化
        String xml = xStream.toXML(student);
        System.out.println(xml);
    }
}
​
@AllArgsConstructor
@ToString
class Student {
    private String studentName;
    private List<Phone> phones;
}
​
@AllArgsConstructor
@ToString
class Phone {
    private String brand;
    private String description;
}

3、執行結果

<student name="張三">
  <phone>
    <brand>小米手機</brand>
    <description>小米手機的描述</description>
  </phone>
  <phone>
    <brand>蘋果手機</brand>
    <description>蘋果手機的描述</description>
  </phone>
</student>

可以看到<name>被作為了<student>的屬性

八、XStream包混疊

1、包混疊用於創建一個類XML的完全限定名稱的別名到一個新的限定名稱。讓我們再次修改原來的XStreamTest02例子,將下面程式碼

xStream.alias("student", Student.class);
xStream.alias("phone", Phone.class);

修改為

xStream.aliasPackage("xx.xx.xx.xx", "io.github.xstream.test02");

2、執行程式碼

package io.github.xstream.test02;
​
import com.thoughtworks.xstream.XStream;
import lombok.AllArgsConstructor;
import lombok.ToString;
​
import java.util.ArrayList;
import java.util.List;
​
public class XStreamTest02 {
    public static void main(String[] args) {
        List<Phone> phones = new ArrayList<>();
        phones.add(new Phone("小米手機", "小米手機的描述"));
        phones.add(new Phone("蘋果手機", "蘋果手機的描述"));
        Student student = new Student("張三", phones);
​
        XStream xStream = new XStream();//需要XPP3庫
//        xStream.alias("student", Student.class);
//        xStream.alias("phone", Phone.class);
        xStream.aliasPackage("xx.xx.xx.xx", "io.github.xstream.test02");
        xStream.aliasField("name", Student.class, "studentName");
        xStream.addImplicitCollection(Student.class, "phones");
        xStream.useAttributeFor(Student.class, "studentName");
​
        //XML序列化
        String xml = xStream.toXML(student);
        System.out.println(xml);
    }
}
​
@AllArgsConstructor
@ToString
class Student {
    private String studentName;
    private List<Phone> phones;
}
​
@AllArgsConstructor
@ToString
class Phone {
    private String brand;
    private String description;
}

3、執行結果

<xx.xx.xx.xx.Student name="張三">
  <xx.xx.xx.xx.Phone>
    <brand>小米手機</brand>
    <description>小米手機的描述</description>
  </xx.xx.xx.xx.Phone>
  <xx.xx.xx.xx.Phone>
    <brand>蘋果手機</brand>
    <description>蘋果手機的描述</description>
  </xx.xx.xx.xx.Phone>
</xx.xx.xx.xx.Student>

可以看到包名由io.github.xstream.test02替換為了xx.xx.xx.xx

九、XStream註解

1、前面的四、五、六、七、八步驟都是通過程式碼操作的

//xStream.alias("student", Student.class);
//xStream.alias("phone", Phone.class);
xStream.aliasPackage("xx.xx.xx.xx", "io.github.xstream.test02");
xStream.aliasField("name", Student.class, "studentName");
xStream.addImplicitCollection(Student.class, "phones");
xStream.useAttributeFor(Student.class, "studentName");

2、XStream同時也支援註解,使用註解會變得簡單也會達到相同的效果

package io.github.xstream.test03;
​
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.*;
import com.thoughtworks.xstream.converters.basic.BooleanConverter;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.ToString;
​
import java.util.ArrayList;
import java.util.List;
​
public class XStreamTest03 {
    public static void main(String[] args) {
        List<Phone> phones = new ArrayList<>();
        phones.add(new Phone("小米手機", "小米手機的描述"));
        phones.add(new Phone("蘋果手機", "蘋果手機的描述"));
        Student student = new Student("張三", phones, 20, true);
        
        XStream xStream = new XStream();//需要XPP3庫
        //xStream.processAnnotations(new Class[]{Student.class});
        xStream.autodetectAnnotations(true);
        //XML序列化
        String xml = xStream.toXML(student);
        System.out.println(xml);
    }
}
​
@AllArgsConstructor
@ToString
//別名註解
@XStreamAlias("student")
class Student {
    @XStreamAlias("name")
    //把欄位節點設置成屬性
    @XStreamAsAttribute
    private String studentName;
    //省略集合根節點
    @XStreamImplicit
    private List<Phone> phones;
    //隱藏欄位
    @XStreamOmitField
    private int age;
    //設置轉換器
    @XStreamConverter(value = BooleanConverter.class, booleans = {false}, strings = {"男", "女"})
    private boolean sex;
}
​
@AllArgsConstructor
@ToString
@XStreamAlias("phone")
class Phone {
    private String brand;
    private String description;
}

3、使用註解的話,需要XML序列化之前添加如下程式碼

xStream.autodetectAnnotations(true);

或者

xStream.processAnnotations(new Class[]{Student.class});

4、執行結果

<student name="張三">
  <phone>
    <brand>小米手機</brand>
    <description>小米手機的描述</description>
  </phone>
  <phone>
    <brand>蘋果手機</brand>
    <description>蘋果手機的描述</description>
  </phone>
  <sex>男</sex>
</student>

使用註解我們也可以看到也能達到相同的效果

注意:當使用XStream對象處理一個被註解的類型時,XStream對象也會處理所有與其相關的類型的註解資訊,即該類型的父類、父介面、所有子類的註解。

十、XStream自定義轉換器

1、XStream自帶的轉換器

    XStream內部有許多轉換器,用於JavaBean對象到XML或JSON之間的轉換。這些轉換器的詳細資訊網址://x-stream.github.io/converters.html

2、使用自定義轉換器

package io.github.xstream.test04;
​
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
​
public class XStreamTest04 {
    public static void main(String[] args) {
        Student student =new Student("張三",19);
        XStream xStream = new XStream();
        //註冊轉換器
        xStream.registerConverter(new StudentConverter());
        //序列化
        String xml = xStream.toXML(student);
        System.out.println(xml);
        //反序列化
        student=(Student)xStream.fromXML(xml);
        System.out.println(student);
    }
}
​
@Getter
@Setter
@ToString
@AllArgsConstructor
class Student {
    private String name;
    private int age;
}

自定義轉換器

package io.github.xstream.test04;
​
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 StudentConverter implements Converter {
    //定義轉換器能轉換的JavaBean類型
    @Override
    public boolean canConvert(Class type) {
        return type.equals(Student.class);
    }
​
    //把對象序列化成XML或JSON
    @Override
    public void marshal(Object value, HierarchicalStreamWriter writer,
                        MarshallingContext context) {
        Student student = (Student) value;
        writer.startNode("姓名");
        writer.setValue(student.getName());
        writer.endNode();
        writer.startNode("年齡");
        writer.setValue(student.getAge() + "");
        writer.endNode();
        writer.startNode("轉換器");
        writer.setValue("自定義的轉換器");
        writer.endNode();
    }
​
    //把XML或JSON反序列化成對象
    @Override
    public Object unmarshal(HierarchicalStreamReader reader,
                            UnmarshallingContext context) {
        Student student = new Student("", -1);
        reader.moveDown();
        student.setName(reader.getValue());
        reader.moveUp();
        reader.moveDown();
        student.setAge(Integer.parseInt(reader.getValue()));
        reader.moveUp();
        return student;
    }
}

3、執行結果

<student>
  <姓名>張三</姓名>
  <年齡>19</年齡>
  <轉換器>自定義的轉換器</轉換器>
</student>
Security framework of XStream not initialized, XStream is probably vulnerable.
Student(name=張三, age=19)

4、常用的轉換器介面與抽象類

SingleValueConverter:單值轉換介面
AbstractSingleValueConverter:單值轉換抽象類
Converter:常規轉換器介面

十一、XStream對象流

1、對象輸出流

package io.github.xstream.test05;
​
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
import lombok.AllArgsConstructor;
import lombok.ToString;
​
import java.io.*;
​
public class XStreamTest05 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        XStreamTest05 xStreamTest04 = new XStreamTest05();
        String path = "F:\\test.txt";
        XStream xStream = new XStream();//需要XPP3庫
        xStream.processAnnotations(Student.class);
        xStream.autodetectAnnotations(true);
        xStreamTest04.writeObject(xStream, path);
    }
​
    //對象輸出流方法
    public void writeObject(XStream xStream, String path) throws IOException {
        Student zs = new Student("張三", 20);
        Student ls = new Student("李四", 21);
        Student ww = new Student("王五", 22);
        ObjectOutputStream objectOutputStream = xStream.createObjectOutputStream(new FileOutputStream(path));
        objectOutputStream.writeObject(zs);
        objectOutputStream.writeObject(ls);
        objectOutputStream.writeObject(ww);
        objectOutputStream.writeObject("totalStudent");
        objectOutputStream.writeInt(3);
        objectOutputStream.close();
    }
}
​
@AllArgsConstructor
@ToString
//別名註解
@XStreamAlias("student")
class Student {
    @XStreamAlias("name")
    //把欄位節點設置成屬性
    @XStreamAsAttribute
    private String studentName;
    private int age;
}

2、在指定路徑中打開test.txt文件,查看執行結果

<object-stream>
  <student name="張三">
    <age>20</age>
  </student>
  <student name="李四">
    <age>21</age>
  </student>
  <student name="王五">
    <age>22</age>
  </student>
  <string>totalStudent</string>
  <int>3</int>
</object-stream>

注意:XStream對象流是通過標準java.io.ObjectOutputStream和java.io.ObjectInputStream對象。因為XML文檔只能有一個根節點,必須包裝在一個序列化的所有元素額外的根節點。這個根節點默認為<object-stream>上面的例子所示。 

3、對象輸入流

package io.github.xstream.test05;
​
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
import lombok.AllArgsConstructor;
import lombok.ToString;
​
import java.io.*;
​
public class XStreamTest05 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        XStreamTest05 xStreamTest04 = new XStreamTest05();
        String path = "F:\\test.txt";
        XStream xStream = new XStream();//需要XPP3庫
        xStream.processAnnotations(Student.class);
        xStream.autodetectAnnotations(true);
        xStreamTest04.readObject(xStream, path);
    }
​
    //對象輸入流方法
    public void readObject(XStream xStream, String path) throws IOException, ClassNotFoundException {
        ObjectInputStream objectInputStream = xStream.createObjectInputStream(new FileInputStream(path));
        System.out.println((Student) objectInputStream.readObject());
        System.out.println((Student) objectInputStream.readObject());
        System.out.println((Student) objectInputStream.readObject());
        System.out.println(objectInputStream.readObject());
        System.out.println(objectInputStream.readInt());
    }
}
​
@AllArgsConstructor
@ToString
//別名註解
@XStreamAlias("student")
class Student {
    @XStreamAlias("name")
    //把欄位節點設置成屬性
    @XStreamAsAttribute
    private String studentName;
    private int age;
}

4、執行結果

Student(studentName=張三, age=20)
Student(studentName=李四, age=21)
Student(studentName=王五, age=22)
totalStudent
3

十二、XStream持久化API

1、保存Java對象

package io.github.xstream.test06;
​
import com.thoughtworks.xstream.persistence.FilePersistenceStrategy;
import com.thoughtworks.xstream.persistence.PersistenceStrategy;
import com.thoughtworks.xstream.persistence.XmlArrayList;
import lombok.AllArgsConstructor;
import lombok.ToString;
​
import java.io.File;
import java.util.List;
​
public class XStreamTest06 {
    public static void main(String[] args) {
        XStreamTest06 xStreamTest06=new XStreamTest06();
        xStreamTest06.saveObject();
    }
​
    //保存Java對象
    public void saveObject(){
        PersistenceStrategy strategy = new FilePersistenceStrategy(new File("F:\\"));
        List list = new XmlArrayList(strategy);
        list.add(new Student("張三",13));
        list.add(new Student("李四",21));
        list.add(new Student("王五",17));
    }
}
​
@ToString
@AllArgsConstructor
class Student {
    private String name;
    private int age;
}

2、運行程式結果,在F磁碟的根路徑可以看到有三個文件:[email protected][email protected][email protected],每個對象都被序列化到XML文件里

3、讀取並刪除JavaBean對象

package io.github.xstream.test06;
​
import com.thoughtworks.xstream.persistence.FilePersistenceStrategy;
import com.thoughtworks.xstream.persistence.PersistenceStrategy;
import com.thoughtworks.xstream.persistence.XmlArrayList;
import lombok.AllArgsConstructor;
import lombok.ToString;
​
import java.io.File;
import java.util.Iterator;
import java.util.List;
​
public class XStreamTest06 {
    public static void main(String[] args) {
        XStreamTest06 xStreamTest06 = new XStreamTest06();
        xStreamTest06.deleteObject();
    }
    
    //讀取並刪除Java對象
    public void deleteObject() {
        PersistenceStrategy strategy = new FilePersistenceStrategy(new File("F:\\"));
        List list = new XmlArrayList(strategy);
        for (Iterator it = list.iterator(); it.hasNext(); ) {
            System.out.println((Student) it.next());
            //刪除對象序列化文件
            it.remove();
        }
    }
}
​
@ToString
@AllArgsConstructor
class Student {
    private String name;
    private int age;
}

4、運行程式結果,可以看到把F磁碟的根路徑[email protected][email protected][email protected]文件刪除了

Security framework of XStream not initialized, XStream is probably vulnerable.
Student(name=張三, age=13)
Student(name=李四, age=21)
Student(name=王五, age=17)

十三、XStream操作JSON

1、XStream序列化JSON的重命名

package io.github.xstream.test07;
​
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver;
import io.github.xstream.test04.StudentConverter;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
​
public class XStreamTest07 {
    public static void main(String[] args) {
        XStreamTest07 xStreamTest07 = new XStreamTest07();
        xStreamTest07.serializeJson();
    }
​
    public void serializeJson() {
        Student student = new Student("張三", 19);
        XStream xStream = new XStream(new JettisonMappedXmlDriver());//設置Json解析器
        xStream.autodetectAnnotations(true);
        //JSON序列化
        String xml = xStream.toXML(student);
        System.out.println(xml);
        //JSON反序列化
        student = (Student) xStream.fromXML(xml);
        System.out.println(student);
    }
}
​
@ToString
@AllArgsConstructor
@XStreamAlias("人")
class Student {
    @XStreamAlias("姓名")
    private String name;
    @XStreamAlias("年齡")
    private int age;
}

2、運行結果

{"人":{"姓名":"張三","年齡":19}}
Student(name=張三, age=19)
Security framework of XStream not initialized, XStream is probably vulnerable.

注意:XStream序列化JSON的重命名的方式與其序列化成XML的方式一樣!

3、去掉序列化JSON的根節點

package io.github.xstream.test07;
​
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
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 io.github.xstream.test04.StudentConverter;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
​
import java.io.Writer;
​
public class XStreamTest07 {
    public static void main(String[] args) {
        XStreamTest07 xStreamTest07 = new XStreamTest07();
        xStreamTest07.removeRootNode();
    }
​
    public void removeRootNode() {
        Student student = new Student("張三", 19);
        XStream xStream = new XStream(new JsonHierarchicalStreamDriver() {
            public HierarchicalStreamWriter createWriter(Writer writer) {
                return new JsonWriter(writer, JsonWriter.DROP_ROOT_MODE);
            }
        });
        //Json序列化
        String xml = xStream.toXML(student);
        System.out.println(xml);
    }
}
​
@ToString
@AllArgsConstructor
@XStreamAlias("人")
class Student {
    @XStreamAlias("姓名")
    private String name;
    @XStreamAlias("年齡")
    private int age;
}

4、運行結果

{
  "name": "張三",
  "age": 19
}

注意:去掉根節點後的JSON串是不能反序列化的,因為XStream不知道它的類型。

5、JSON的解析器區別

前面兩個例子使用了不同的JSON解析器,這裡說明他們的不同之處:

  1. JettisonMappedXmlDriver:是支援序列化和反序列化Json的。

  2. JsonHierarchicalStreamDriver:只支援序列化,不支援反序列化。

 

參考:

    //x-stream.github.io

    //www.yiibai.com/xstream

    //www.cnblogs.com/LiZhiW/p/4313493.html

● 別在 Java 程式碼里亂打日誌了,這才是正確的打日誌姿勢!

● 高可用Redis服務架構分析與搭建

● 8 種方案,幫你解決重複提交問題!請拿走

 IDEA 解決 Maven 依賴衝突的高能神器,這一篇夠不夠?

● 你連微服務的網關都說不清楚,還天天鼓搗著要把項目拆分微服務?

Tags: