XStreamユーザーガイド:オブジェクトのXMLへの変換
1. 概要
このチュートリアルでは、XStreamライブラリを使用してJavaオブジェクトをXMLにシリアル化する方法を学習します。
2. 特徴
XStreamを使用してXMLをシリアル化および逆シリアル化することには、いくつかの興味深い利点があります。
-
適切に構成すると、非常にclean XMLが生成されます
-
XML出力のcustomizationに重要な機会を提供します
-
循環参照を含むobject graphsのサポート
-
ほとんどのユースケースでは、XStreamインスタンスはthread-safe, once configuredです(アノテーションを使用する場合は注意が必要です)
-
問題の診断に役立つ明確なメッセージがexception handlingの間に提供されます
-
バージョン1.4.7以降、特定のタイプのシリアル化を禁止するためにsecurity featuresを使用できるようになりました
3. プロジェクトのセットアップ
プロジェクトでXStreamを使用するには、次のMaven依存関係を追加します。
com.thoughtworks.xstream
xstream
1.4.9
4. 基本的な使い方
XStreamクラスは、APIのファサードです。 XStreamのインスタンスを作成するときは、スレッドセーフの問題にも注意を払う必要があります。
XStream xstream = new XStream();
インスタンスが作成および設定されると、注釈処理を有効にしない限り、マーシャリング/アンマーシャリングのために複数のスレッドで共有される場合があります。
4.1. 運転者
DomDriver、StaxDriver、XppDriverなどのいくつかのドライバーがサポートされています。 これらのドライバーには、異なるパフォーマンスとリソースの使用特性があります。
XPP3ドライバーはデフォルトで使用されますが、もちろんドライバーを簡単に変更できます。
XStream xstream = new XStream(new StaxDriver());
4.2. XMLの生成
–Customerの単純なPOJOを定義することから始めましょう。
public class Customer {
private String firstName;
private String lastName;
private Date dob;
// standard constructor, setters, and getters
}
次に、オブジェクトのXML表現を生成しましょう。
Customer customer = new Customer("John", "Doe", new Date());
String dataXml = xstream.toXML(customer);
デフォルト設定を使用すると、次の出力が生成されます。
John
Doe
1986-02-14 03:46:16.381 UTC
この出力から、含まれているタグがデフォルトでCustomerの完全修飾クラス名を使用していることがはっきりとわかります.
デフォルトの動作がニーズに合わないと判断する理由はたくさんあります。 たとえば、アプリケーションのパッケージ構造を公開するのは不安かもしれません。 また、生成されるXMLは大幅に長くなります。
5. エイリアス
aliasは、デフォルトの名前ではなく、要素に使用する名前です。
たとえば、Customerクラスのエイリアスを登録することで、com.example.pojo.Customerをcustomerに置き換えることができます。 クラスのプロパティのエイリアスを追加することもできます。 エイリアスを使用することで、XML出力をはるかに読みやすく、Java固有のものを少なくすることができます。
5.1. クラスエイリアス
エイリアスは、プログラムで、または注釈を使用して登録できます。
ここで、Customerクラスに@XStreamAliasアノテーションを付けましょう。
@XStreamAlias("customer")
次に、この注釈を使用するようにインスタンスを構成する必要があります。
xstream.processAnnotations(Customer.class);
または、プログラムでエイリアスを設定する場合は、次のコードを使用できます。
xstream.alias("customer", Customer.class);
エイリアス構成とプログラム構成のどちらを使用する場合でも、Customerオブジェクトの出力ははるかにクリーンになります。
John
Doe
1986-02-14 03:46:16.381 UTC
5.2. フィールドエイリアス
クラスのエイリアスに使用されるのと同じ注釈を使用して、フィールドのエイリアスを追加することもできます。 たとえば、XML表現でフィールドfirstNameをfnに置き換えたい場合は、次のアノテーションを使用できます。
@XStreamAlias("fn")
private String firstName;
または、同じ目標をプログラムで達成することもできます。
xstream.aliasField("fn", Customer.class, "firstName");
aliasFieldメソッドは、使用するエイリアス、プロパティが定義されているクラス、エイリアスするプロパティ名の3つの引数を受け入れます。
どちらの方法を使用しても、出力は同じです。
John
Doe
1986-02-14 03:46:16.381 UTC
5.3. デフォルトのエイリアス
クラス用に事前登録されたエイリアスがいくつかあります。これらのいくつかを次に示します。
alias("float", Float.class);
alias("date", Date.class);
alias("gregorian-calendar", Calendar.class);
alias("url", URL.class);
alias("list", List.class);
alias("locale", Locale.class);
alias("currency", Currency.class);
6. コレクション
次に、Customerクラス内にContactDetailsのリストを追加します。
private List contactDetailsList;
コレクション処理のデフォルト設定では、これは出力です。
John
Doe
1986-02-14 04:14:05.874 UTC
6673543265
0124-2460311
4676543565
0120-223312
contactDetailsListの親タグ,を省略する必要があり、各ContactDetails要素をcustomer要素の子にしたい場合を考えてみましょう。 例をもう一度変更しましょう。
xstream.addImplicitCollection(Customer.class, "contactDetailsList");
これで、XMLが生成されるときに、ルートタグが省略され、次のXMLになります。
John
Doe
1986-02-14 04:14:20.541 UTC
6673543265
0124-2460311
4676543565
0120-223312
アノテーションを使用しても同じことが実現できます。
@XStreamImplicit
private List contactDetailsList;
7. コンバーター
XStreamは、Converterインスタンスのマップを使用し、それぞれに独自の変換戦略があります。 これらは、提供されたデータをXMLの特定の形式に変換し、再び元に戻します。
デフォルトのコンバーターを使用することに加えて、デフォルトを変更したり、カスタムコンバーターを登録したりできます。
7.1. 既存のコンバーターの変更
XStream(DateConverter)によって提供される_ using the default settings. We can modify the custom converter for _Dateタグが生成される方法に満足できなかったとします。
xstream.registerConverter(new DateConverter("dd-MM-yyyy", null));
上記は、「dd-MM-yyyy」形式で出力を生成します。
John
Doe
14-02-1986
7.2. カスタムコンバーター
また、前のセクションと同じ出力を実現するカスタムコンバーターを作成することもできます。
public class MyDateConverter implements Converter {
private SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy");
@Override
public boolean canConvert(Class clazz) {
return Date.class.isAssignableFrom(clazz);
}
@Override
public void marshal(
Object value, HierarchicalStreamWriter writer, MarshallingContext arg2) {
Date date = (Date)value;
writer.setValue(formatter.format(date));
}
// other methods
}
最後に、MyDateConverterクラスを次のように登録します。
xstream.registerConverter(new MyDateConverter());
オブジェクトを文字列に変換するように設計されたSingleValueConverterインターフェイスを実装するコンバーターを作成することもできます。
public class MySingleValueConverter implements SingleValueConverter {
@Override
public boolean canConvert(Class clazz) {
return Customer.class.isAssignableFrom(clazz);
}
@Override
public String toString(Object obj) {
SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy");
Date date = ((Customer) obj).getDob();
return ((Customer) obj).getFirstName() + ","
+ ((Customer) obj).getLastName() + ","
+ formatter.format(date);
}
// other methods
}
最後に、MySingleValueConverterを登録します。
xstream.registerConverter(new MySingleValueConverter());
MySingleValueConverterを使用すると、CustomerのXML出力は次のようになります。
John,Doe,14-02-1986
7.3. コンバーターの優先順位
Converterオブジェクトを登録するときに、それらの優先度レベルを設定することもできます。
コンバーターは、明示的な優先順位で登録できます。 デフォルトでは、XStream.PRIORITY_NORMALに登録されています。 同じ優先順位のコンバーターは、登録された逆の順序で使用されます。 デフォルトのコンバーター、つまり 他に登録されているコンバータが適切でない場合に使用されるコンバータは、優先度XStream.PRIORITY_VERY_LOWで登録できます。 XStreamは、デフォルトでReflectionConverterをフォールバックコンバーターとして使用します。
APIは、いくつかの名前付き優先度値を提供します。**
private static final int PRIORITY_NORMAL = 0;
private static final int PRIORITY_LOW = -10;
private static final int PRIORITY_VERY_LOW = -20;
8. フィールドの省略
注釈またはプログラム構成を使用して、生成されたXMLからフィールドを省略できます。 注釈を使用してフィールドを省略するには、問題のフィールドに@XStreamOmitField注釈を適用するだけです。
@XStreamOmitField
private String firstName;
プログラムでフィールドを省略するには、次の方法を使用します。
xstream.omitField(Customer.class, "firstName");
どちらの方法を選択しても、出力は同じです。
Doe
14-02-1986
9. 属性フィールド
要素自体ではなく、要素の属性としてフィールドをシリアル化したい場合があります。 contactTypeフィールドを追加するとします。
private String contactType;
contactTypeをXML属性として設定する場合は、@XStreamAsAttributeアノテーションを使用できます。
@XStreamAsAttribute
private String contactType;
または、同じ目標をプログラムで達成することもできます。
xstream.useAttributeFor(ContactDetails.class, "contactType");
上記のいずれの方法の出力も同じです。
6673543265
0124-2460311
10. 並行性
XStreamの処理モデルにはいくつかの課題があります。 インスタンスを構成すると、スレッドセーフになります。
注釈の処理は、マーシャリング/アンマーシャリングの直前に構成を変更することに注意することが重要です。 そのため、アノテーションを使用してインスタンスをオンザフライで構成する必要がある場合は、通常、スレッドごとに個別のXStreamインスタンスを使用することをお勧めします。
11. 結論
この記事では、XStreamを使用してオブジェクトをXMLに変換する基本について説明しました。 また、XML出力がニーズを満たすようにするために使用できるカスタマイズについても学びました。 最後に、注釈に関するスレッドセーフの問題を調べました。
このシリーズの次回の記事では、XMLをJavaオブジェクトに戻す方法について学びます。
この記事の完全なソースコードは、リンクされたGitHub repositoryからダウンロードできます。