2016-07-13 22 views
1

Es gibt eine einfache Klasse Bean1 mit einer Unterliste vom Typ .JAXB override @XmlElement Typ der Liste

Ich versuche, die Klasse zu überschreiben, um den Typ der Liste zu ändern. Die neue Kindklasse (d. H. BeanChild2) erweitert die vorhergehende (d. H. BeanChild1).

public static class Bean2 extends Bean1 
{ 
    public Bean2() 
    { 
    super(); 
    } 

    @Override 
    @XmlElement(name="child", type=BeanChild2.class) 
    public List<BeanChild1> getChildList() 
    { 
    return super.getChildList(); 
    } 
} 

public static class BeanChild2 extends BeanChild1 { } 

So, hier ist, wie ich es getestet:

public static void main(String[] args) 
{ 
    String xml = "<bean>" + 
       " <child></child>" + 
       " <child></child>" + 
       " <child></child>" + 
       "</bean>"; 
    Reader reader = new StringReader(xml); 

    Bean2 b2 = JAXB.unmarshal(reader, Bean2.class); 
    assert b2.getChildList().get(0) instanceof BeanChild2; // fails 
} 

Der Test zeigt, dass, dass diese Liste noch Childs von BeanChild1 enthält.

Also, wie kann ich zwingen, das childList Feld mit BeanChild2 Instanzen zu füllen?

Wenn es keine einfachen Lösungen gibt, dann fühlen sich frei, um mehr kreative Lösungen zu schreiben (zB mit XmlAdapter s, Unmarshaller.Listener, vielleicht eine zusätzliche Anmerkung auf dem Elternteil oder Kind Klasse ...)

Antwort

0

Es gibt keine Möglichkeit, um die @XmlElement Annotation einer Superklasse zu ändern (zB zu überschreiben). Zumindest keine Anmerkungen verwenden.

  • Es spielt keine Rolle, was Sie (zum Beispiel FIELD, PROPERTY, PUBLIC, NONE) verwenden @XmlAccessorType.
  • Es macht keinen Unterschied, wenn Sie die Anmerkungen auf die Felder oder auf die Getters setzen.

Allerdings gibt es eine sinnvolle Alternative. Die MOXy-Implementierung von JAXB bietet die Möglichkeit define the metadata/bindings in an xml file. Tatsächlich hat jede Java Annotation eine XML Alternative. Aber es wird besser: Sie können sowohl Java-Anmerkungen und diese XML-Metadaten kombinieren. Die coole Sache, ist, dass MOXy beide Deklarationen zusammenführen wird, und im Konfliktfall die XML-definierten Metadaten eine höhere Priorität bekommen.

Angenommen, dass die Bean1 Klasse wie oben mit Anmerkungen versehen ist. Dann ist es möglich, die Bindung in einer XML-Datei neu zu definieren. Beispiel:

<xml-bindings xml-accessor-type="PROPERTY"> 
    <java-types> 
    <java-type name="Bean1"> 
     <xml-element java-attribute="childList" name="child" 
        type="BeanChild2" container-type="java.util.ArrayList" /> 
    </java-type> 
    </java-types> 
</xml-bindings> 

Diese neue Bindungsdatei wird während der Erstellung des Kontextobjekts benötigt.

// use a map to reference the xml file 
Map<String, Object> propertyMap = new HashMap<>(); 
propertyMap.put(JAXBContextProperties.OXM_METADATA_SOURCE, "bindings.xml"); 

// pass this properyMap during the creation of the JAXB context. 
JAXBContext context = JAXBContext.newInstance(..., propertyMap); 

moxy wird die Java-Annotationen und die XML-Bindungen, und im Falle eines Konflikts die XML definierten Einstellungen angewendet werden fusionieren. In diesem Fall wird die frühere Annotation @XmlElement(name=child) durch eine XML-Definition ersetzt, die @XmlElement(name=child, type=BeanChild2.class) entspricht. Sie können mehr über die XML-Bindungen here lesen.