XStream は、アノテーションによるXMLに対するJava Object のマッピング、コンバータの指定ができていいのだけど、
stackoverflow.com
ここで書かれたように NULL を 中身空のタグでXMLを書く場合に指定方法が文字列、String型でしか逃げ道がない。
stackoverflow に投稿されたように、ReflectionConverter を書き直して 配布されてる XStream ライブラリに手を加える
なんてやってられない。
日付や時刻のとき、困るだろう。
これとは論点が違う話で。。。
皆(特に日本だけ?)、なぜか、年月日の表現を、yyyy-MM-dd のハイフン区切りの書式を嫌がり、yyyy/MM/dd になってる
ことが多い。
XStream でこの書式を解決するのは、com.thoughtworks.xstream.converters.Converter 実装を用意するか
com.thoughtworks.xstream.converters.time.LocalDateConverter を継承して書式を任意に指定させるかである。
Converter 実装の例
import java.time.LocalDate; import java.time.format.DateTimeFormatter; import com.thoughtworks.xstream.converters.Converter; import com.thoughtworks.xstream.converters.MarshallingContext; import com.thoughtworks.xstream.converters.UnmarshallingContext; import com.thoughtworks.xstream.io.HierarchicalStreamReader; import com.thoughtworks.xstream.io.HierarchicalStreamWriter; public class CustomLocalDateConverter implements Converter{ private String format; public CustomLocalDateConverter(String format){ this.format = format; } @Override public boolean canConvert(Class type){ return type.equals(LocalDate.class); } @Override public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context){ LocalDate date = (LocalDate)value; writer.setValue(date.format(DateTimeFormatter.ofPattern(format))); } @Override public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context){ try{ return LocalDate.parse(reader.getValue(), DateTimeFormatter.ofPattern(format)); }catch(Exception e){ return null; } } }
LocalDateConverter を継承の例
import java.time.LocalDate; import java.time.format.DateTimeFormatter; import com.thoughtworks.xstream.converters.ConversionException; import com.thoughtworks.xstream.converters.time.LocalDateConverter; public class CustomLocalDateConverter extends LocalDateConverter{ private String format; public CustomLocalDateConverter(String format){ this.format = format; } @Override public Object fromString(final String str){ try{ return LocalDate.parse(str, DateTimeFormatter.ofPattern(format)); }catch(Exception e){ final ConversionException exception = new ConversionException("Cannot parse value as local date", e); exception.add("value", str); throw exception; } } @Override public String toString(final Object obj){ if (obj==null){ return ""; } return DateTimeFormatter.ofPattern(format).format((LocalDate)obj); } }
任意のフィールドを日付のタグ、 <date> に割り当てる場合
@XStreamAlias("date") @XStreamConverter(value=CustomLocalDateConverter.class, strings={"yyyy/MM/dd"}) public LocalDate birthday;
ここで、どうしても、 この LocalDate bithday が、null の時、このままでは、<date></date> と書かれるXMLが
生成できないので、、、
強引なトリックを使うなら、この bithday 宣言の前に、NULL の時に XML出力時専用のフィールドを文字列で用意することだ。
@XStreamAlias("date") @XStreamConverter(value=CustomLocalDateConverter.class, strings={"yyyy/MM/dd"}) public LocalDate birthday; @XStreamAlias("date") public String writeOnlyDate = "";
@XStreamAlias を2回やってしまうのである。これがなぜかエラーにならない。
上の例では、birthday が、NULL の時、writeOnlyDate = "" が有効になって、 <date></date> が出力される。
そもそも、XML離れが進んでる傾向が強いので、久々にこれらXML系を調べたけど、
相変わらず、これ1本で。。。というフレームワーク、ツール、ライブラリが見当たらない。。。
>>>つづき、、、
oboe2uran.hatenablog.com