JAXBでJavaクラスからXML schema生成 - torutkの日記の続きです。
Javaのクラスでjava.util.Calendar型のデータをJAXBでXMLに出力すると、XML Schema上はxs:dateTimeにマッピングされます。
具体的な出力形式は、
dateTime="2011-10-01T23:00:00.261+09:00"
のように、年-月-日T時:分:秒.ミリ秒+タイムゾーン(オフセット) という書式となります。
Calendar型を、日付として使っている場合、あるいは日時としているが秒、ミリ秒、タイムゾーンは使用しない場合、上述の形式はちょっと不便です。
XML上で日時の形式を自由に設定したいところですが、その方法が見当たりませんでした。
そこで、JavaのクラスのCalendar型をXML上では文字列(xs:string)にマッピングするようにJAXBアノテーションで指定し、Calendar型と文字列を変換するアダプターを作成します。
まず、昨日のMeasureクラスにアノテーションを追加します。
@XmlAttribute @XmlJavaTypeAdapter(XmlDateAdapter.class) private Calendar dateTime;
@XmlJavaTypeAdapterアノテーションを追加し、作成するアダプタークラス(後述)を指定します。
アダプタークラスXmlDateAdapterを作成します。
package jp.gr.java_conf.torutk.weather; import javax.xml.bind.annotation.adapters.XmlAdapter; import java.util.Calendar; import java.util.Date; import java.text.SimpleDateFormat; public class XmlDateAdapter extends XmlAdapter<String, Calendar> { private SimpleDateFormat dateFormat = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" ); @Override public Calendar unmarshal(String xmlDateTime) throws Exception { Date date = dateFormat.parse(xmlDateTime); Calendar cal = Calendar.getInstance(); cal.setTime(date); return cal; } @Override public String marshal(Calendar calendar) throws Exception { return String.format("%1$tF %1$tT", calendar); } }
アダプタークラスは、XmlAdapter
型パラメータValueTypeはJAXBが対応可能な型、BoundTypeはこのアダプターでJAXB対応可能な型と結び付ける(通常はユーザー定義の)型です。
- SimpleDateFormatはマルチスレッドセーフでないので、フィールドではなくローカル変数で定義すべきかもしれません。JAXBがXmlAdapterをマルチスレッドで呼ぶ可能性があるかは調査していません。
このクラスを追加してコンパイルし、実行すると
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <ns2:weather xmlns:ns2="http://java-conf.gr.jp/torutk/weather"> <measures> <measure dateTime="2011-10-01 22:00:00" windSpeed="3" windDirection="122" humidity="55.0" temperature="21.5"/> <measure dateTime="2011-10-01 23:00:00" windSpeed="2" windDirection="140" humidity="58.0" temperature="20.8"/> </measures> </ns2:weather>
と日付の書式がアダプターで指定した形になりました。
- あれ、なぜかweatherに名前空間が追加されるようになった。不思議だ・・・