JavaSE6からJAXB2.0が標準で使えるようである。
javax.xml.bind パッケージとして含まれている。
POJOからXMLをマーシャリング(marshaling - 整列)、その逆をアンマーシャリング(unmarshalling 無秩序化)という。
マーシャリング(POJO->XML)の例を上げる。
クラスにXmlRootElementをアノテーションする。
import java.util.Calendar;
import java.util.Date;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Message {
private long id;
private Date postDate;
private String name;
private String comment;
//constructor,getter,setter,etc...
}
これを、XMLにマーシャリングするには、次のコードを使用する。
import java.util.Date;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
public class Test {
public static void main( String[] args ) throws Exception {
//アノテーションされたPOJOをインスタンス化
Message message = new Message( 1, new Date(), "yamazaki", "Hello World" );
//マーシャラーを取得。
Marshaller marshaller = JAXBContext.newInstance( Message.class ).createMarshaller();
//標準出力へマーシャリング
marshaller.marshal( message, System.out );
}
}
結果:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><message><comment>Hello World</comment><id>1</id><name>yamazaki</name><postDate>2010-02-18T00:46:47.366+09:00</postDate></message>一行でコンパクトに表示される。改行を入れたい場合は、マーシャラーに次のプロパティをセットする。
...
//マーシャラーを取得。
Marshaller marshaller = JAXBContext.newInstance( Message.class ).createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
...
すると、見やすくなる。
結果:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<message>
<comment>Hello World</comment>
<id>1</id>
<name>yamazaki</name>
<postDate>2010-02-18T00:52:24.009+09:00</postDate>
</message>
素晴らしい。
次に、上記のMessageというオブジェクトのリストを扱いたい。
期待する結果は、次のようなもの。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<messages>
<message>
<comment>test comment #1</comment>
<id>1</id>
<name>noname</name>
<postDate>2010-02-18T00:55:18.359+09:00</postDate>
</message>
<message>
<comment>test comment #2</comment>
<id>2</id>
<name>noname</name>
<postDate>2010-02-18T00:55:18.359+09:00</postDate>
</message>
<message>
<comment>test comment #3</comment>
<id>3</id>
<name>noname</name>
<postDate>2010-02-18T00:55:18.359+09:00</postDate>
</message>
</messages>
ちょっと、工夫を要した。残念ながら、Listオブジェクトとして直接、XMLにマップする方法は発見できなかったので、次のラッパーのようなクラスを作ることにした。
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlAccessorType( value=XmlAccessType.FIELD)
@XmlRootElement(name="messages")
public class MessageList {
@XmlElement( name="message" )
private List<Message> messages;
public MessageList() {
this.messages = new ArrayList<Message>();
}
public List<Message> getMessages() {
return messages;
}
public void setMessages(List<Message> messages) {
this.messages = messages;
}
}
テスト:
public class MessageUnit {
public static void main( String[] args ) throws Exception {
MessageList messages = new MessageList();
messages.getMessages().add(new Message(1, "test comment #1"));
messages.getMessages().add(new Message(2, "test comment #2"));
messages.getMessages().add(new Message(3, "test comment #3"));
Marshaller marshaller = JAXBContext.newInstance( MessageList.class ).createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal( messages, System.out );
}
}
これで、期待する結果が得られる。
POJOを必要な時にXMLで取得できるのは極めて強力で便利である。
オブジェクトを10000個作成してマーシャリングし、標準出力を捨てると、実行時間は、以下のとおりだった。
コード:
public class MessageUnit {
public static void main( String[] args ) throws Exception {
MessageList messages = new MessageList();
//10000個のMessageオブジェクトを追加
for( int i = 0; i < 10000; i++ ) {
messages.getMessages().add( new Message( i, "comment #" + i ) );
}
Marshaller marshaller = JAXBContext.newInstance( MessageList.class ).createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal( messages, System.out );
}
}
# time java restwitter.MessageUnit > /dev/null
実行時間:
real 0m0.724s
user 0m0.502s
sys 0m0.087s
#
10万個で次の結果。
実行時間:
real 0m2.277s
user 0m1.783s
sys 0m0.175s
AMD Athron64 2.4GHz 3800+ (Single Core) 一世代前のCPU。
速度的にも、悪くない。