首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

XStream 實現 JavaBean 與 XML/JSON 雙向轉換完整指南

     編輯:Java 相關知識

前言

XStream 是功能強大的 Java 序列化庫,支援 JavaBean 與 XML、JSON 雙向轉換,無需依賴 Getter/Setter,透過反射直接存取私有欄位。本文詳細介紹 XStream 核心用法、別名機制、驅動選擇與進階技巧。

環境準備

  • 核心 JAR:xstream-1.4.x.jar (無額外依賴)
  • JSON 支援需額外:jettison-1.x.jar (JettisonMappedXmlDriver 使用)
  • 可選 XML 驅動:xpp3, jdom, dom4j 等

領域模型定義

public class Customer {
    private int custId;
    private String custName;
    private List orders;
    // 建構子、Getter/Setter 省略
}

public class Order {
    private int orderId;
    private String orderName;
    private Product[] products;
    // 建構子、Getter/Setter 省略
}

public class Product {
    private int prodId;
    private String prodName;
    private double prodPrice;
    // 建構子、Getter/Setter 省略
}

一、JavaBean → XML

基本用法

XStream xstream = new XStream(new DomDriver()); // 使用 JDK 內建 DOM
// 或 new XStream() 預設使用 XppDriver (需 xpp3.jar)

Customer customer = buildSampleCustomer();
String xml = xstream.toXML(customer);
System.out.println(xml);

輸出 (未設別名)

<com.unmi.model.Customer>
  <custId>1</custId>
  <custName>Unmi</custName>
  <orders>
    <com.unmi.model.Order>
      <orderId>101</orderId>
      <orderName>電器類</orderName>
      <products>
        <com.unmi.model.Product>
          <prodId>1001</prodId>
          <prodName>電腦</prodName>
          <prodPrice>4000.0</prodPrice>
        </com.unmi.model.Product>
      </products>
    </com.unmi.model.Order>
  </orders>
</com.unmi.model.Customer>

設定別名美化輸出

xstream.alias("customer", Customer.class);
xstream.alias("order", Order.class);
xstream.alias("product", Product.class);
// 也可批量:xstream.aliasPackage("pkg", "com.unmi.model");

輸出 (設別名後)

<customer>
  <custId>1</custId>
  <custName>Unmi</custName>
  <orders>
    <order>
      <orderId>101</orderId>
      <orderName>電器類</orderName>
      <products>
        <product>
          <prodId>1001</prodId>
          <prodName>電腦</prodName>
          <prodPrice>4000.0</prodPrice>
        </product>
      </products>
    </order>
  </orders>
</customer>

其他輸出重載

xstream.toXML(customer, System.out);                    // 直接寫入 OutputStream
xstream.toXML(customer, new FileWriter("customer.xml")); // 寫入檔案

二、JavaBean → JSON

使用 JsonHierarchicalStreamDriver (輸出較緊湊)

XStream xstream = new XStream(new JsonHierarchicalStreamDriver());
xstream.alias("customer", Customer.class);
xstream.alias("order", Order.class);
xstream.alias("product", Product.class);
xstream.toXML(customer, new PrintWriter(System.out));

輸出

{
  "customer": {
    "custId": 1,
    "custName": "Unmi",
    "orders": [{
      "orderId": 101,
      "orderName": "電器類",
      "products": [
        {"prodId": 1001, "prodName": "電腦", "prodPrice": 4000.0},
        {"prodId": 1002, "prodName": "空調", "prodPrice": 2000.0}
      ]
    }]
  }
}

使用 JettisonMappedXmlDriver (單行輸出,需 jettison.jar)

XStream xstream = new XStream(new JettisonMappedXmlDriver());
// 別名設定相同
xstream.toXML(customer, System.out);

輸出為單行 JSON,適合網路傳輸。

三、XML → JavaBean

XStream xstream = new XStream(new DomDriver());
xstream.alias("product", Product.class); // 必須設別名對應 XML 節點

String xml = "1001電腦4000.0";
Product product = (Product) xstream.fromXML(xml);
System.out.println(product.getProdName()); // 輸出: 電腦

fromXML 重載方法

Object fromXML(String xml);
Object fromXML(InputStream input);
Object fromXML(Reader reader);
Object fromXML(InputStream input, Object root);  // 反序列化到現有物件
Object fromXML(Reader reader, Object root);

四、JSON → JavaBean

// 必須使用 JettisonMappedXmlDriver
XStream xstream = new XStream(new JettisonMappedXmlDriver());
xstream.alias("product", Product.class);

String json = "{product:{prodId: 1001, prodName: '電腦', prodPrice: 4000.0}}";
Product product = (Product) xstream.fromXML(json);
System.out.println(product.getProdName()); // 輸出: 電腦

驅動選擇對照表

驅動類別方向依賴特點
DomDriverXML ↔ Object無 (JDK 內建)標準 DOM,無額外依賴
XppDriverXML ↔ Objectxpp3.jar高效能 Pull 解析
JsonHierarchicalStreamDriverObject → JSON無輸出層級式 JSON,可讀性好
JettisonMappedXmlDriverJSON ↔ Objectjettison.jar雙向 JSON,單行輸出

進階技巧

1. 欄位屬性化 (Field as Attribute)

xstream.useAttributeFor(Customer.class, "custId");
// 輸出: ...

2. 忽略欄位

xstream.omitField(Customer.class, "orders");

3. 自定義 Converter

xstream.registerConverter(new Converter() {
    public boolean canConvert(Class type) { return type == LocalDate.class; }
    public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
        writer.setValue(((LocalDate)source).format(DateTimeFormatter.ISO_DATE));
    }
    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
        return LocalDate.parse(reader.getValue(), DateTimeFormatter.ISO_DATE);
    }
});

4. 隱式集合

xstream.addImplicitCollection(Customer.class, "orders");
// XML 可簡化為 ......

5. 安全性設定 (XStream 1.4.7+)

// 僅允許特定類別防止反序列化漏洞
XStream xstream = new XStream();
XStream.setupDefaultSecurity(xstream);
xstream.allowTypes(new Class[]{Customer.class, Order.class, Product.class});
xstream.allowTypesByWildcard(new String[]{"com.myapp.model.**"});

XStream vs JSON-lib vs Jackson

特性XStreamJSON-libJackson
XML 支援✅ 優秀❌ 無✅ (Jackson XML)
JSON 支援✅ 良好✅ 基礎✅ 業界標準
無 Getter/Setter✅ 支援❌ 需要❌ 需要
效能中等較低極高
Spring 整合良好一般原生支援

建議:新專案首選 Jackson;需同時支援 XML/JSON 且不想引入多個庫時選 XStream;舊專案維護可繼續使用 JSON-lib。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved