2013-03-06 14 views
7

Czy ktoś wie, jak dołączyć niestandardowe XmlAdapter do obiektów zawartych w heterogenicznej liście (np. Lista)? Na przykład - załóżmy, że mamy klasę pojemnik z listy Różne obiektów:JAXB: XmlAdapter dla listy <Object> pozycji

@XmlRootElement(name = "container") 
public class Container { 
    private List<Object> values = new ArrayList<Object>(); 

    @XmlElement(name = "value") 
    public List<Object> getValues() { 
     return values; 
    } 

    public void setValues(List<Object> values) { 
     this.values = values; 
    } 
} 

Jeśli stawiamy String -s, -s Integer i tak dalej będą mapowane domyślnie. Załóżmy teraz, że chcemy umieścić niestandardowego obiektu:

public class MyObject { 
    //some properties go here 
} 

Oczywistym rozwiązaniem jest napisanie własnego adaptera:

public class MyObjectAdapter extends XmlAdapter<String, MyObject> { 
    //marshalling/unmarshalling 
} 

Ale niestety to nie działa z pakietem poziomie @XmlJavaTypeAdapter - adapter prostu nigdy tak się nazywa, więc marszałkowanie się nie udaje. I nie mogę go zastosować bezpośrednio do getValues(), ponieważ mogą istnieć inne typy obiektów. @XmlJavaTypeAdapter działa tylko wtedy, gdy mam pole typu MyObject w pojemnik (również z poziomu pakietu annotaton):

public class Container { 
    private MyObject myObject; 
} 

Ale to nie jest to, co chcę - chcę listę dowolnych obiektów. Używam standardowej implementacji JAXB firmy Sun:

<dependency> 
    <groupId>com.sun.xml.bind</groupId> 
    <artifactId>jaxb-impl</artifactId> 
    <version>2.2.3-1</version> 
</dependency> 

Jakieś pomysły, jak wykonać mapowanie?

P.S .: Jedno małe wyjaśnienie - Chciałbym uniknąć adnotacji MyObject z adnotacjami JAXB. Może to być klasa z biblioteki innej firmy, której nie mam pod kontrolą. Tak więc wszelkie zmiany powinny znajdować się poza MyObject.

+0

"ContextResolver" może być dobrym rozwiązaniem tutaj ... – Mark

Odpowiedz

0

Możesz spróbować zmienić swój MyObjectAdapter, aby rozszerzyć XmlAdapter<String, List<Object>>. Tak powinno to wyglądać mniej więcej tak:

public class MyObjectAdapter extends XmlAdapter<String, List<Object>> { 
    //marshalling/unmarshalling 
} 

Kiedy również dodać adnotację XmlJavaTypeAdapter do getter w swojej klasie Container, powinno działać.

@XmlRootElement(name = "container") 
public class Container { 
    private ArrayList<Object> values = new ArrayList<Object>(); 

    @XmlElement(name = "value") 
    @XmlJavaTypeAdapter(MyObjectAdapter.class) 
    public ArrayList<Object> getValues() { 
     return values; 
    } 

    public void setValues(ArrayList<Object> values) { 
     this.values = values; 
    } 
}