XStreamを使ってXML-Object変換のUtilクラスを作ってみた
XStreamは、XMLとJavaオブジェクトのマッピングができます。
XMLファイルからシリアライズ、デシリアライズもできますが、
今回は、文字列としてのXMLとオブジェクトの変換してるだけです。
package org.ryu1.utils; import com.thoughtworks.xstream.XStream; /** * XMLUtilクラス. */ public final class XmlUtil { private XmlUtil() { } /** * XML文字列をオブジェクトに変換します * @param clazz * @param xml * @return object of clazz */ @SuppressWarnings("unchecked") public static <T> T fromXML(Class<T> clazz, String xml) { XStream xstream = new XStream(); xstream.processAnnotations(clazz); return (T) xstream.fromXML(xml); } /** * オブジェクトをXML文字列に変換します * @param obj * @return String of XML */ public static <T> String toXML(T obj) { XStream xstream = new XStream(); xstream.processAnnotations(obj.getClass()); return xstream.toXML(obj); } }
ちょっぴり、背伸びして、Genericを使い、キャストの手間を省いてみました。
fromXMLだけ、クラスを渡さないといけないのが、かっこわるいです。
使い方のサンプルはこちら。
package org.ryu1.utils; import com.thoughtworks.xstream.annotations.XStreamAlias; import java.util.ArrayList; import java.util.List; public class XmlUtilTest { @org.junit.Test public void testFromXML() throws Exception { String xml = "<parent>\n" + " <name>John</name>\n" + " <age>40</age>\n" + " <children>\n" + " <child>\n" + " <name>Micheal</name>\n" + " <age>12</age>\n" + " </child>\n" + " <child>\n" + " <name>Jessica</name>\n" + " <age>7</age>\n" + " </child>\n" + " </children>\n" + "</parent>"; Parent john = XmlUtil.fromXML(Parent.class, xml); System.out.println(john); } @org.junit.Test public void testToXML() throws Exception { Parent john = new Parent(); john.setAge(40); john.setName("John"); Child micheal = new Child(); micheal.setAge(12); micheal.setName("Micheal"); Child jessica = new Child(); jessica.setAge(7); jessica.setName("Jessica"); List<Child> children = new ArrayList<Child>(); children.add(micheal); children.add(jessica); john.setChildren(children); String xml = XmlUtil.toXML(john); System.out.println(xml); } /******************************************************************** ここから下は、上記のテストメソッドで使用している XMLに相互変換するクラスの定義です。 *********************************************************************/ @XStreamAlias("parent") public static class Parent { @XStreamAlias("name") private String name; @XStreamAlias("age") private int age; @XStreamAlias("children") private List<Child> children; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public List<Child> getChildren() { return children; } public void setChildren(List<Child> children) { this.children = children; } @Override public String toString() { return "Parent{" + "name='" + name + '\'' + ", age=" + age + ", children=" + children + '}'; } } @XStreamAlias("child") public static class Child { @XStreamAlias("name") private String name; @XStreamAlias("age") private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Child{" + "name='" + name + '\'' + ", age=" + age + '}'; } } }
サンプルでは、Parentクラスのインスタンスをxmlにしたり、xmlからParentインスタンスをつくってます。
XMLの要素名は、何もしないと、クラス名とか変数名になります。
個人的な好みで、XMLに、キャメルケースを使用したくなかったので、@XStreamAliasというアノテーションをつけ、XMLに任意の要素名をつけることにしました。
また、@XStreamAliasを使用するためには、以下のメソッドを実行して、アノテーションをONにしてやります。
xstream.processAnnotations(obj.getClass());
んで、それぞれSYSOしているところの出力は、こちらです。
testFromXML
<parent> <name>John</name> <age>40</age> <children> <child> <name>Micheal</name> <age>12</age> </child> <child> <name>Jessica</name> <age>7</age> </child> </children> </parent>
testToXML
Parent{name='John', age=40, children=[Child{name='Micheal', age=12}, Child{name='Jessica', age=7}]}
Parentは、childrenというChildクラスのListをもっていますが、ちゃんと表現されていますね。
ここにはありませんが、他にも、Mapも通常の配列[]もいけるようです。
どこまで、うまく変換できるのか興味深いところですね。
Sample Source: ryu1/utils · GitHub