2013年03月27日

JavaオブジェクトをXMLへシリアライズ, デシリアライズする時に知っておきたいライブラリ2選 - Simple & XStream

データベースを使う程では無いがオブジェクの状態を保存しておきたい、そんな時にはJavaオブジェクトのシリアライズ(直列化)、デシリアライズ(非直列化)が頭に浮かびます。この方法には幾つかありますが、シリアライズされたデータを人が理解・編集出来る、外部システム/他言語間でのデータ交換にも利用することを望むのであればXMLフォーマットは大変便利です。
 
僕はアプリケーションの設定ファイル <-> Java オブジェクト変換に使うことが多いですね。

application-x-zoo

今日は Simple/XStream という2つのJavaライブラリの使い方・特徴を紹介します。 

Simpleを使ったJavaオブジェクトのXMLシリアライズとデシリアライズ


Simpleはその名の通りシンプル、高速を謳うシリアライズ・フレームワークで、実は僕もXMLへのシリアライズといえば最近までSimpleライブラリというイメージを持っていました。

まずは、プロジェクト・ページから最新のライブラリをダウンロードしましょう。

Simple 2.7

ダウンロードしたsimple-xml-x.x.x.jarをクラスパスに含めれば準備はおしまい。

simple_01


ここでは2つのクラスを使ってシリアライズ、デシリアライズしてみます。

まずはシンプルなItemクラス。

public class Item {

 private String name = null;
 
 private double price = 0.0;
 
 private String descr = "";

 public Item(String name, double price) {
  this.name = name;
  this.price = price;
 }
 
 public Item() {  
 }
 
 public String getName() {
  return name;
 }

 public double getPrice() {
  return price;
 }

 public String getDescr() {
  return descr;
 }

 public void setDescr(String descr) {
  this.descr = descr;
 }

}

後もうひとつ、ItemオブジェクトをListに保存するStockクラスを用意します。

import java.util.ArrayList;
import java.util.List;

public class Stock {
 
 private String label = "Item stock";
 
 private List<Item> items = new ArrayList<Item>();
 
 public void addItem(Item i) {
  items.add(i);
 }
 
 public Item getItem(int i) {
  return items.get(i);
 }
 
 public int getNumStocks() {
  return items.size();
 }
 
 public boolean removeItem(Item i) {
  return items.remove(i);
 }

 public String getLabel() {
  return label;
 }

 public void setLabel(String label) {
  this.label = label;
 }
}

Simpleを使う場合、この2つのクラスにアノテーションを追加します。

import org.simpleframework.xml.Element;

public class Item {
 
 @Element
 private String name = null;
 
 @Element
 private double price = 0.0;
 
 @Element(required = false)
 private String descr = "";

 
 public Item(String name, double price) {
  this.name = name;
  this.price = price;
 }
 
 public Item() {  
 }
 
 public String getName() {
  return name;
 }

 public double getPrice() {
  return price;
 }

 public String getDescr() {
  return descr;
 }

 public void setDescr(String descr) {
  this.descr = descr;
 }
 
}

@Element は要素、required = false は必須値では無いことを指し示します。同じようにStockクラスも次のように変更します。

import org.simpleframework.xml.Element;

public class Item {
 
 @Element
 private String name = null;
 
 @Element
 private double price = 0.0;
 
 @Element(required = false)
 private String descr = "";

 
 public Item(String name, double price) {
  this.name = name;
  this.price = price;
 }
 
 public Item() {  
 }
 
 public String getName() {
  return name;
 }

 public double getPrice() {
  return price;
 }

 public String getDescr() {
  return descr;
 }

 public void setDescr(String descr) {
  this.descr = descr;
 }
 
}

Stockクラスではlabelを属性とする為に @Attribute アノテーションを新たに使っています。

ここまで出来たらまずはシリアライズ(直列化)してみます。次のコードはStock/Itemインスタンスを生成し、Persisterを使ってstock.xmlにシリアライズしています。

  Stock stock = new Stock();
  stock.addItem(new Item("りんご", 100.0));
  stock.addItem(new Item("みかん", 50.0));
  stock.addItem(new Item("ぶどう", 150.0));
Serializer serializer = new Persister(); File xml = new File("stock.xml"); serializer.write(stock, new BufferedWriter(new FileWriter(xml)));

stock.xmlを開いてみると・・・無事XMLへのシリアライズが行われました。

<stock label="Item stock">
  <items class="java.util.ArrayList">
    <item>
      <name>りんご</name>
      <price>100.0</price>
      <descr></descr>
    </item>
    <item>
      <name>みかん</name>
      <price>50.0</price>
      <descr></descr>
    </item>
    <item>
      <name>ぶどう</name>
      <price>150.0</price>
      <descr></descr>
    </item>
  </items>
</stock>

デシリアライズも基本は同じ。read()メソッドを使ってオブジェクト化します。

  Serializer serializer = new Persister();
  File xml = new File("stock.xml");
  Stock stock = serializer.read(Stock.class, xml);
for (int i=0; i< stock.getNumStocks(); i++) { System.out.println(stock.getItem(i).getName()); }

実行すると次のような出力になるはずです。

りんご
みかん
ぶどう

詳しい使い方は Tutorial ページをどうぞ。


XStreamを使ったJavaオブジェクトのXMLシリアライズとデシリアライズ


XStreamもSimpleと同じくJavaオブジェクトのシリアライズ、デシリアライズを行いますが、より”シンプル”です。

まずはプロジェクト・ページから Binary distribution をダウンロードしましょう。

XStream - About XStream

zipファイルに含まれるjarファイルのうち、最低限必要になるのはxstream-x.x.x.jarとxstream/xpp3_min-x.x.x.jar, xstream/xmlpull-x.x.x.x.jarの3つ。

これをクラスパスに含めれば準備はおしまい。

 xstream_01

早速、Simpleと同じくStock、Itemオブジェクトをシリアライズしてみましょう。

こちらがそのコード。

  Stock stock = new Stock();
  stock.addItem(new Item("りんご", 100.0));
  stock.addItem(new Item("みかん", 50.0));
  stock.addItem(new Item("ぶどう", 150.0));
  
  XStream xs = new XStream();
  xs.useAttributeFor(Stock.class, "label");
  File xml = new File("stock.xml");
  xs.toXML(stock, new BufferedWriter(new FileWriter(xml)));

え、アノテーションは必要ないのか?、そうなんです。XStreamではアノテーションは必須ではないんです(使えますが)。
 
このメリットは対象となるクラスにシリアライズに関わるコードが含まれなくなることです。IBM developerWorks JapanのSimple紹介ページではSimple利用すれば対象オブジェクトは POJO (Plain Old Java Object) のままで良いと紹介していますが、これを見る限りXStreamの方がよりPOJOですね。

尚、アノテーションを使わない分、useAttrbuteFor()メソッドで属性になる変数名を指定してあげる手間は必要です。

生成されたstock.xmlの中身がこちら。

<Stock label="Item stock">
  <items>
    <Item>
      <name>りんご</name>
      <price>100.0</price>
      <descr></descr>
    </Item>
    <Item>
      <name>みかん</name>
      <price>50.0</price>
      <descr></descr>
    </Item>
    <Item>
      <name>ぶどう</name>
      <price>150.0</price>
      <descr></descr>
    </Item>
  </items>
</Stock>

Simpleとは少し違ってJavaのコードに関する情報は含まれません(Simpleを使った場合にも、Stockクラスの書き方次第ではJava具象クラスの情報を消すことができます)。

この他にもXStreamでは要素の alias 名も簡単に利用出来るという特徴があります。先ほどのコードに次の一行を追加すれば、<Item> 要素は <アイテム>に置換してXML出力されます。

- snip -
xs.alias("アイテム", Item.class);

こちらもItemクラスへのアノテーション(@XStreamAlias("アイテム"))追加で実装することも可能。

最後にデシリアライズ。これは次のようなコードになります。

  XStream xs = new XStream();
  xs.useAttributeFor(Stock.class, "label");
  Stock stock = (Stock) xs.fromXML(xml);

うーん、XStreamは始めて触ったんですが、こちらの方が柔軟性があって迷う人にはオススメだなあ。

XStreamのチュートリアルはこちらからどうぞ。


Simple/XStreamのシリアライズ・デシリアライズ性能比較


Simple、XStreamどちらも高速を謳っていますが、同じ条件ならばどちらが早いのでしょうか?

Itemオブジェクトを100000(10万)件ストックしたStockオブジェクトのシリアライズ、デシリアライズ所要時間を計測した結果がこちら。

Simple XStream
シリアライズ(ミリ秒) 3237 1778
デシリアライズ(ミリ秒 1582 2412

比較的にXStreamはシリアライズが早く、Simpleはデシリアライズが早いという結果になりました。

双方の時間を合わせればXStreamに軍配が上がるので性能面ではXStreamの勝ち・・・かな?


最新Javaコーディング作法  プロが知るべき、107の規約と21の心得
森崎 雅稔
日経BP社
売り上げランキング: 137,854

XML Hacks ―エキスパートのためのデータ処理テクニック
Michael Fitzgerald 佐藤 直生 木下 哲也 福竜興業
オライリージャパン
売り上げランキング: 270,580

Posted by netbuffalo at 08:00│Comments(0)TrackBack(0)Java | プログラミング


この記事へのトラックバックURL

http://trackback.blogsys.jp/livedoor/netbuffalo/4415606

コメントする

名前
URL
 
  絵文字