JYaml は Java でYAMLを扱うためのライブラリです。現在のバージョンは1.3となっています。本家サイトは以下です。
http://jyaml.sourceforge.net/index.html
使用するには jyaml の jar をクラスパスに追加するだけです。
YAMLについて
XMLと比較して簡素で理解しやすいファイルフォーマットで、Rubyでは主流の?ファイルフォーマットです。詳細は以下を参照ください。
http://yaml.org/
日本語だと以下がまとまってます。
http://jp.rubyist.net/magazine/?0009-YAML
シーケンスのシリアライズとデシリアライズ
オブジェクトのYAMLへのシリアライズは Yaml.dump メソッドを使用します。
List<String> list = new ArrayList<String>(); list.add("seq1"); list.add("seq2"); Yaml.dump(list, new File("object.yml"));
object.yml が作成され、以下の内容が出力されます。
--- - seq1 - seq2
上記ファイルをデシリアライズするには Yaml.load メソッドを使用します。
Object obj = Yaml.load(new File("object.yml")); System.out.println(obj);
以下の出力となり、Listへ読み込みが行われていることが確認できます。
[seq1, seq2]
マップのシリアライズとデシリアライズ
マップに関しても同様です。
Map<String, String> map = new HashMap<String, String>(); map.put("key1", "value1"); map.put("key2", "value2"); Yaml.dump(map, new File("object.yml"));
object.yml が作成され、以下の内容が出力されます。
--- key2: value2 key1: value1
同じようにデシリアライズすると
Object obj = Yaml.load(new File("object.yml")); System.out.println(obj);
マップとしてデシリアライズされていることが確認できます。
{key2=value2, key1=value1}
オブジェクトのシリアライズ
以下のようなPersonオブジェクトをシリアライズしてみます。シリアライズするクラスはデフォルトコンストラクタが必要です。
package etc9; public class Person { private String name; private int age; public Person() {} public Person(String name, int age) { this.name=name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
シリアライズは今までと同じように
Person p = new Person("Thom", 33); Yaml.dump(p, new File("object.yml"));
以下のようなYAMLファイルが出力されます。
--- !etc9.Person age: 33 name: Thom
デシリアライズはYaml.loadとすることで YAMLの !etc9.Person の該当オブジェクトがロードされます。
dumpメソッドに追加で引数を渡し、以下のようにシリアライズすると、
Person p = new Person("Thom", 33); Yaml.dump(p, new File("object.yml"), true);
以下のように対応クラスのタグが出力されなくなります。
--- age: 33 name: Thom
この場合は、以下のように、マッピング対象のクラスを指定してデシリアライズします。クラスを指定しない場合は上記の例だと、単なる Map としてデシリアライズされます。
Person p = Yaml.loadType(new File("object.yml"), Person.class);
ネストしたオブジェクト
Personクラスにchildという属性を追加してみます。
package etc9; public class Person { private String name; private int age; private Person child; ・・・ public Person getChild() { return child; } public void setChild(Person child) { this.child = child; } }
同じ流れでシリアライズ。
Person p = new Person("Thom", 33); p.setChild(new Person("Mick", 5)); Yaml.dump(p, new File("object.yml"));
出力ファイルは以下の内容となります。
--- !etc9.Person age: 33 child: !etc9.Person age: 5 name: Mick name: Thom
dump の第2引数に true を指定した場合は
Person p = new Person("Thom", 33); p.setChild(new Person("Mick", 5)); Yaml.dump(p, new File("object.yml"), true);
以下のような出力となります。
--- age: 33 child: age: 5 name: Mick name: Thom
デシリアライズは同様に以下のように行うことができます。
Person r = Yaml.loadType(new File("object.yml"), Person.class);
複数オブジェクトのシリアライズ
複数のオブジェクトのシリアライズには YamlEncoder を使うことができます。以下のようにすると、
Person p1 = new Person("Thom", 33); Person p2 = new Person("Mick", 5); YamlEncoder enc = new YamlEncoder(new FileOutputStream("object.yml")); enc.writeObject(p1); enc.writeObject(p2); enc.close();
以下の内容のファイルが作成されます。
--- !etc9.Person age: 33 name: Thom --- !etc9.Person age: 5 name: Mick
イテレータを持つコレクションの場合には、以下のように簡単に書くこともできます。
Yaml.dumpStream(collection.iterator(), file);
デシリアライズは以下のように YamlDecoder を使います。
YamlDecoder dec = new YamlDecoder(inputStream); try { while (true){ Object object = dec.readObject(); /* do something useful */ } } catch (EOFException e){ System.out.println("Finished reading stream."); } finally dec.close(); }
以下のように書くこともできます。
for (Object object: Yaml.loadStream(input)){
・・・
}
または、以下のように型を指定することもできます。
for (Person p: Yaml.loadStreamOfType(input, Person.class)){ ・・・ }