前回はまず使ってみるということで、単純なJavaオブジェクトからXMLへ変換する方法を解説しました。
今回は、XMLからJavaオブジェクトへ変換する方法と、また一歩進んでバインディングを制御するアノテーションについて解説します。
データ構造としては前回と同じものを使いましょう。
会社(従業員*)
従業員(名前,給料)
これらを表すJavaクラスも前回と基本は同じなのですが、オブジェクトの中身を見たいのでtoString()を追加しています。
Campanyクラス
public class Company {
private List<Employee> employees;
public List<Employee> getEmployees() {
return employees;
}
public void setEmployees(List<Employee> employees) {
this.employees = employees;
}
@Override
public String toString() {
String str = "Company [n";
if (employees != null) {
for (Employee e : employees) {
str += " " + e + "n";
}
}
str += "]";
return str;
}
}
Employeeクラス
public class Employee {
private String name;
private int salary;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Employee [name=" + name + ", salary=" + salary + "]";
}
}
では、XMLをこのクラスのオブジェクトに変換するプログラムがどうなるか見てみましょう。実際的にはXMLをファイルから読み込むなどすると思いますが、この例ではその場で文字列を作っています。
public class Sample2 {
public static void main(String[] args) {
String xml = "<?xml version="1.0" encoding="UTF-8" standalone="yes"?>"
+ "<company>"
+ " <employees>"
+ " <name>taro</name>"
+ " <salary>1000</salary>"
+ " </employees>"
+ " <employees>"
+ " <name>hanako</name>"
+ " <salary>800</salary>"
+ " </employees>"
+ "</company>";
// アンマーシャル
Company c = JAXB.unmarshal(new StringReader(xml), Company.class);
System.out.println(c);
}
}
これも前回同様ごく簡単ですね。JAXB#unmarshall()を呼ぶだけです。
実行すると以下の出力が得られます。
Company [ Employee [name=taro, salary=1000] Employee [name=hanako, salary=800] ]
これで無事にXMLからJavaオブジェクトへ変換できました。
さてこのように特に設定をしなくても、自動的にJavaオブジェクトとXMLとが(正確にはJavaクラスとXML Schemaとが)対応付けられて相互に変換できるわけですが、このままでは都合が悪いこともあります。
前回も触れたように、XML上、従業員の要素名が「employees」になっています。これはなぜかと言うとCompanyクラスのプロパティ名が「employees」だからです。もちろんプロパティ名を「employee」に変えれば要素名も変わるのですが、いつも都合良くプログラムを変えたり、XMLを変えたりできるとは限りません。
そこで登場するのがアノテーションです。Companyクラスを以下のようにしてみましょう。
public class Company {
private List<Employee> employees;
@XmlElementWrapper
@XmlElement(name="employee")
public List<Employee> getEmployees() {
return employees;
}
public void setEmployees(List<Employee> employees) {
this.employees = employees;
}
@Override
public String toString() {
String str = "Company [n";
if (employees != null) {
for (Employee e : employees) {
str += " " + e + "n";
}
}
str += "]";
return str;
}
}
名前からだいたい想像がつくかもしれませんね。このクラスを使ってJavaオブジェクトからXMLへの変換(前回のSample1)を行ってみると、以下のような出力が得られます。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<company>
<employees>
<employee>
<name>taro</name>
<salary>1000</salary>
</employee>
<employee>
<name>hanako</name>
<salary>800</salary>
</employee>
</employees>
</company>
つまりそれぞれのアノテーションは以下のような働きをします。
Employeeクラスの方も少し変えてみましょう。せっかくXMLなのですから属性を使いたいときもあるでしょう。
public class Employee {
private String name;
private int salary;
@XmlAttribute
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@XmlAttribute
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Employee [name=" + name + ", salary=" + salary + "]";
}
}
これで再び変換を実行すると、出力は以下のように変わります。
<company>
<employees>
<employee salary="1000" name="taro"/>
<employee salary="800" name="hanako"/>
</employees>
</company>
ここまでで、JavaオブジェクトとXMLとの間をかなり自由に行き来できるようになりました。
次回は先延ばしにしていたXML Schemaが登場する予定です。JAXBのコマンド(CLI)を使ってJavaクラスとXML Schemaの変換を行います。