今回は java の話。
Java のシリアライズって、本来の目的であるオブジェクトの永続化という意味では結構使い勝手がいいです。
しかし、設定ファイルにXML用いる場合など、"人が見る” or "人が書く" 事を目的とした場合は非常に使いにくいと言わざるを得ません。
また、場合によっては、シリアライズに対応させるためにコードの可読性・安全性を下げる結果にもなります。
本来 private にしておきたい項目まで public にせざるを得ない場合もあります。
つまり、細かい不満点までまとめると・・・
- 作られるXMLファイルの形が気にくわない
- シリアライズ対応の為に、コードの安全性・可読性を下げたくない
- JAXP周りが鬱陶しい…一行で読み込ませろ!
という不満点があるわけです。
はっきりいって、java は嫌いです。 エンタープライズにおいては優秀な言語であることは認めますが、あくまで趣味の範囲で使う言語としては不向きです。
しかし…開発環境の整えやすさ、ライブラリの充実度、クロスプラットフォーム、ランタイムの普及率、この辺りはかなり便利です。 嫌いでも使う意味があります。
というわけで、自分仕様の Java用 XMLシリアライザ 作ってみました。
目的は
- 綺麗なXMLファイルを読み書きする
(人が気持ちよく読み書きしやすいように、クラス名等はXMLに含めない)
- シリアライズの為にコードを汚さない
(アクセッサやアクセス修飾子を強要しない)
- 一行で読み書きできる
(Javaの流儀から反しますが、気にしない)
あたりを達成することにします。
とりあえず気合いで作ってみました。
実際のデータクラス定義はこの通りになりました。
JAVA:
-
@XmlNode
-
public class Configure {
-
@XmlValue
private Integer count=
20;
-
@XmlValue
("file") private String filename =
"./result.txt";
-
private User[] users;
-
-
public Configure(){
-
users = new User[3];
-
users[0] = new User("御手洗", "某会長");
-
users[1] = new User("山田", "花子さん?");
-
users[2] = new User("鈴木", "古都町の鈴木さん");
-
}
-
}
-
-
@XmlNode
-
public class User {
-
private static int tindex = 0;
-
-
@XmlAttribute
private Integer index = tindex++;
-
@XmlValue
private String name =
"";
-
@XmlValue
private String info =
"";
-
-
private User(){
-
}
-
-
-
this.name = name;
-
this.info = info;
-
}
-
}
という感じにデータ定義クラスを書けます。
数値型や文字列型に対しては XmlAttribute / XmlValue を指定することで、出力対象になります。 XmlValue("xxx") と書くことで出力時に別名をつけれます。
クラスの定義時に XmlNode を指定すると そのクラスが XMLの出力対象になります。private な項目でもおkです。 読み込みonly な設定情報クラスであれば、メンバ変数を pulicにする必要も、セッターメソッドを用意する必要もありません。
XmlNode を指定したクラスの配列も出力対象となります。
XmlNode なクラスは無引数のコンストラクタを必要としますが、private でOKです。
本来であれば List/Set/Map も対象にしたかったのですが、クラスの型情報がコンパイル時に保持されないので断念しました。 Java ならジェネリクス型の List/Set/Map を用いたいところですが、実装が型消去による実装なので、実行時に型情報を取得できません orz
ちなみに、以下が このクラスのシリアライズ/デシリアライズ のコードになります。
・シリアライズ
JAVA:
-
Configure config = new Configure();
-
XmlDataDocument.
save(config,
new File("test.xml"));
・デシリアライズ
JAVA:
-
Configure config =
(Configure
)XmlDataDocument.
load(Configure.
class,
new File("test.xml"));
やっぱ、これくらいの単純さがいいです(´・ー・`)
ちなみに、出力されたXMLファイルは以下のようになります。
XML:
-
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-
<configure>
-
<count>20</count>
-
<file>./result.txt</file>
-
<users>
-
<user index="0">
-
<name>御手洗</name>
-
<info>某会長</info>
-
</user>
-
<user index="1">
-
<name>山田</name>
-
<info>花子さん?</info>
-
</user>
-
<user index="2">
-
<name>鈴木</name>
-
<info>古都町の鈴木さん</info>
-
</user>
-
</users>
-
</configure>
こんな感じになります。
だいたい見てわかると思いますが、構造はアノテーションとリフレクトを多用して得ています。どうせならこの構造情報を元に DTDも出力できるようにしてもいいかもしれません。
とりあえず、まだ作りたての超アルファ版なので、コードはまだ出しません ←
・・・恥ずかしいからな!(^ω^;
エラーメッセージも適当だし\(^o^)/
今後は、IXMLEvent を実装したクラスでは、シリアライズ前後のイベントを拾えるようにしてみたり、IXMLNodeを実装したクラスは自由にノードを扱えるようにとかしてみようと企んでます。
あえて、コンパイル済みのバイナリとjavadoc をおいておくぜ!
もし使いたい人とかいたら、もうちょっと修正してソースも公開しちゃうぜ(`・ω・´)
xmldata
xmldata.javadoc
・・・今ふと思ったけど、同様の記述方式で O/R マッパー書いても面白いかもしれない。
あくまで、超簡易な入出力のみの・・・。
テーブル作成と、スキーマ表示、簡単な検索、データの挿入、削除、編集・・・ができればいい気がします。
こんなイメージかな・・・?
JAVA:
-
@DBTable
-
public class SampleTable {
-
-
-
@DBReference Category category;
-
}
-
-
@DBTable
-
public class Category {
-
-
-
}
うーん、これだけ書いておいたら、
JAVA:
-
DB db =
new SQLite
(new File("data.db"));
-
// DB db = new MySQL("sample_db");
-
-
db.checkAndCreateTable(SampleTable.class);
-
SampleTable[] ts = db.select("・・・この辺どうしよう/(^o^)\・・・");
こんな感じで使えるようにするとか!
妄想は進むけど・・・実際作ると面倒なんだろうなw