XStream 是功能強大的 Java 序列化庫,支援 JavaBean 與 XML、JSON 雙向轉換,無需依賴 Getter/Setter,透過反射直接存取私有欄位。本文詳細介紹 XStream 核心用法、別名機制、驅動選擇與進階技巧。
xstream-1.4.x.jar (無額外依賴)jettison-1.x.jar (JettisonMappedXmlDriver 使用)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 省略
}
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")); // 寫入檔案
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}
]
}]
}
}
XStream xstream = new XStream(new JettisonMappedXmlDriver());
// 別名設定相同
xstream.toXML(customer, System.out);
輸出為單行 JSON,適合網路傳輸。
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()); // 輸出: 電腦
Object fromXML(String xml);
Object fromXML(InputStream input);
Object fromXML(Reader reader);
Object fromXML(InputStream input, Object root); // 反序列化到現有物件
Object fromXML(Reader reader, Object root);
// 必須使用 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()); // 輸出: 電腦
| 驅動類別 | 方向 | 依賴 | 特點 |
|---|---|---|---|
| DomDriver | XML ↔ Object | 無 (JDK 內建) | 標準 DOM,無額外依賴 |
| XppDriver | XML ↔ Object | xpp3.jar | 高效能 Pull 解析 |
| JsonHierarchicalStreamDriver | Object → JSON | 無 | 輸出層級式 JSON,可讀性好 |
| JettisonMappedXmlDriver | JSON ↔ Object | jettison.jar | 雙向 JSON,單行輸出 |
xstream.useAttributeFor(Customer.class, "custId");
// 輸出: ...
xstream.omitField(Customer.class, "orders");
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);
}
});
xstream.addImplicitCollection(Customer.class, "orders");
// XML 可簡化為 ... ...
// 僅允許特定類別防止反序列化漏洞
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 | JSON-lib | Jackson |
|---|---|---|---|
| XML 支援 | ✅ 優秀 | ❌ 無 | ✅ (Jackson XML) |
| JSON 支援 | ✅ 良好 | ✅ 基礎 | ✅ 業界標準 |
| 無 Getter/Setter | ✅ 支援 | ❌ 需要 | ❌ 需要 |
| 效能 | 中等 | 較低 | 極高 |
| Spring 整合 | 良好 | 一般 | 原生支援 |
建議:新專案首選 Jackson;需同時支援 XML/JSON 且不想引入多個庫時選 XStream;舊專案維護可繼續使用 JSON-lib。