Map<Integer,String>
XmlAdapter
을 Map<Object,Object>
을 지원하는 것으로 조정하려고합니다. 접근이 문서를 기반으로 : XmlAdapter - JAXB's Secret Weapon사용자 지정지도 <Object, Object> XmlAdapter
테스트 하네스이 줄 NullPointerException
생성 : 예상대로
JAXBContext jc = JAXBContext.newInstance(Foo.class);
나는 하네스 및 MapAdapter/MapEntry를 변경하는 경우
는T<Integer,String>
로, 코드가 작동합니다.
무엇이 누락 되었습니까? Object
형식을 직렬화 할 수 있습니까? 아니면 덜 추상적 인 클래스로 캐스팅해야합니까? 그렇다면 marshal()
메서드에서이 오류가 발생할 것이라고 생각하지만 최소한이 점에 도달 한 것 같습니다 (최소한 Netbean의 디버거에서는).
MapEntryType :
public class MyMapEntryType {
@XmlAttribute
public Object key;
@XmlValue
public Object value;
}
지도 유형 :
이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가이 객체를 보는 것만으로 어떤 serializer를 사용할 수 있는지 결정할 수있는 방법은 무엇입니까? "공통"유형의 빌트인 직렬 기가 될 수 있지만 알 수없는 유형에는 체인에 또 다른 어댑터가 필요합니다. –
그래서 비 공통 유형마다 XmlAdapter가 필요합니까? – craig
예. String, Date, List, 모든 프리미티브와 같은 기본 유형은 이미 지원되지만 나머지는 명시 적으로이 방식으로 선언하거나 다른 방식으로 (비공개) 직렬화하는 방법이 필요합니다. 여기서 핵심은 JAXB가 마샬링이 수행되지 않을 때 컨텍스트가 생성 될 때 모든 클래스 (및 가능한 XML 매핑)의 메타 모델을 구축한다는 점입니다. Object 형의 경우 JAXB는 마샬링 할 수있는 방법을 발견 할 방법이 없습니다. 'Object' 뒤에 숨기고 싶은 XML 조각이 다양하다면, 당신은 ['@XmlAnyElement'] (http://stackoverflow.com/questions/9040695) 길을 갈 필요가 있습니다. –