Map<Integer,String>
XmlAdapter
をMap<Object,Object>
に対応させようとしています。アプローチは、この資料に基づいています。XmlAdapter - JAXB's Secret Weaponカスタムマップ<Object、Object> XmlAdapter
この行は、テストハーネスでNullPointerException
を生成します。
JAXBContext jc = JAXBContext.newInstance(Foo.class);
私はT<Integer,String>
するハーネスとMapAdapter/MapEntryを変更する場合、期待どおり、コードが動作します。
私には何が欠けていますか? Object
タイプをシリアライズすることはできますか、抽象度の低い別のクラスとしてキャストする必要がありますか?もしそうなら、私はmarshal()
メソッドでこのエラーに遭遇すると思いますが、少なくともNetBeansのデバッガではこの点に達することはありません。
MapEntryType:
public class MyMapEntryType {
@XmlAttribute
public Object key;
@XmlValue
public Object value;
}
のMapType:
public class MyMapType {
public List<MyMapEntryType> entry = new ArrayList<MyMapEntryType>();
}
MapAdapter:非整列化/整列化する
public final class MyMapAdapter extends
XmlAdapter<MyMapType,Map<Object, Object>> {
@Override
public MyMapType marshal(Map<Object, Object> arg0) throws Exception {
MyMapType myMapType = new MyMapType();
for(Entry<Object, Object> entry : arg0.entrySet()) {
MyMapEntryType myMapEntryType = new MyMapEntryType();
myMapEntryType.key = entry.getKey();
myMapEntryType.value = entry.getValue();
myMapType.entry.add(myMapEntryType);
}
return myMapType;
}
@Override
public Map<Object, Object> unmarshal(MyMapType arg0) throws Exception {
HashMap<Object, Object> hashMap = new HashMap<Object, Object>();
for(MyMapEntryType myEntryType : arg0.entry) {
hashMap.put(myEntryType.key, myEntryType.value);
}
return hashMap;
}
}
、オブジェクト:
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Foo {
@XmlJavaTypeAdapter(MyMapAdapter.class)
Map<Object, Object> map = new HashMap<Object, Object>();
public Map getMap() {
return map;
}
public void setMap(Map map) {
this.map = map;
}
}
テストハーネス:
Map<Object,Object> xyz = new HashMap<Object,Object>();
xyz.put("key0", "value0");
xyz.put("key1", "value1");
Foo foo = new Foo();
foo.setMap(xyz);
//generates NullPointerException
JAXBContext jc = JAXBContext.newInstance(Foo.class);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(foo, System.out);
スタックトレース:
java.lang.NullPointerException
at com.sun.xml.internal.bind.v2.runtime.reflect.TransducedAccessor.get(TransducedAccessor.java:154)
at com.sun.xml.internal.bind.v2.runtime.property.ValueProperty.<init>(ValueProperty.java:66)
at com.sun.xml.internal.bind.v2.runtime.property.PropertyFactory.create(PropertyFactory.java:95)
at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.<init>(ClassBeanInfoImpl.java:145)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getOrCreate(JAXBContextImpl.java:479)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getOrCreate(JAXBContextImpl.java:498)
at com.sun.xml.internal.bind.v2.runtime.property.ArrayElementProperty.<init>(ArrayElementProperty.java:97)
at com.sun.xml.internal.bind.v2.runtime.property.ArrayElementNodeProperty.<init>(ArrayElementNodeProperty.java:47)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at com.sun.xml.internal.bind.v2.runtime.property.PropertyFactory.create(PropertyFactory.java:113)
at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.<init>(ClassBeanInfoImpl.java:145)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getOrCreate(JAXBContextImpl.java:479)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getOrCreate(JAXBContextImpl.java:498)
at com.sun.xml.internal.bind.v2.runtime.property.SingleElementNodeProperty.<init>(SingleElementNodeProperty.java:90)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at com.sun.xml.internal.bind.v2.runtime.property.PropertyFactory.create(PropertyFactory.java:113)
at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.<init>(ClassBeanInfoImpl.java:145)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getOrCreate(JAXBContextImpl.java:479)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:305)
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1100)
at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:143)
at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:110)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:228)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:215)
at javax.xml.bind.ContextFinder.find(ContextFinder.java:414)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:618)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:565)
を私は(私もこれに合わせて、内部のすべてのオブジェクトを変更)、より良い私のニーズを表現するためにMap<String,Object>
にMap<Object,Object>
から地図を変えました。 MyMapEntryType
クラスのObjectプロパティに@XmlAnyElement
と@XmlMixed
注釈を追加しました。注釈@XmlValue
を削除しました。
私はコードをデバッグする場合、この行はエラー(万歳)生成しません:読み込みエラーで
xyz.put("key0", 1);
結果:このエントリをマーシャリングしようとする、しかし
JAXBContext jc = JAXBContext.newInstance(PropertyBag.class);
を:
unable to marshal type `java.lang.Integer` as an element because it is missing an `@XmlRootElement` annotation
私は間違っているかもしれませんが、私はJAXBがタイプを探求できないと思います。あなたのオリジナルのケースでは、あなたは 'MyMapEntryType'にオブジェクトを持っています。配列はオブジェクト、マップはオブジェクト、プリミティブラッパーはオブジェクト、その他の複合クラスインスタンスはオブジェクトです。このオブジェクトを見るだけで、どのシリアライザを使用するのかをJAXBがどのように判断するのですか?これは「共通」型の組み込みシリアライザにすることができますが、未知の型にはチェーン内に別のアダプタが必要です。 –
だから、非共通型ごとにXmlAdapterが必要でしょうか? – craig
はい。 String、Date、List、すべてのプリミティブのような基本型はすでにサポートされていますが、それ以外の場合は明示的に宣言する必要があります。ここでの主なポイントは、マーシャリングが行われたときではなく、コンテキストの作成時にJAXBがすべてのクラス(および可能なXMLマッピング)のメタモデルを構築することです。タイプ 'Object'では、JAXBはマーシャルする方法を見つける方法がありません。 'Object'の背後に隠したいXMLの部分が変化している場合、あなたは[' @XmlAnyElement'](http://stackoverflow.com/questions/9040695)に行く必要があります。 –