2011-08-18 4 views
2

J'ai une classe que je souhaite remplir avec le contenu d'un fichier XML en utilisant JAXB. Mon fichier XML ressemble à ceci:Unmarshalling un TreeSet dans JAXB

<root> 
    <mylist> 
    <item id="1">First Item</item> 
    <item id="2">Second Item</item> 
    </mylist> 
</root> 

Mes JAXB classes annotées ressemblent:

@XmlRootElement 
class MyParentClass { 

    // I always populate this with a TreeSet 
    private Set<MyFieldItem> items; 

    public void setItems(Set<MyFieldItem> items) { 
    this.items = items; 
    } 

    @XmlElementWrapper("mylist") @XmlElement("item") 
    public Set<MyFieldItem> getItems() { 
    return items; 
    } 
} 

class MyFieldItem implements Comparable<MyFieldItem> { 
    private Integer id; 
    private String value; 

    public void setId(Integer id) { 
    this.id = id; 
    } 

    @XmlAttribute 
    public Integer getId() { 
    return id; 
    } 

    public void setValue(String value) { 
    this.value = value; 
    } 

    @XmlValue 
    public String getValue() { 
    return value; 
    } 

    public int compareTo(MyfieldItem o) { 
    return this.id.compareTo(o.getId()); 
    } 
} 

Je trouve que cet arrangement sérialise mes objets à XML correctement, mais lorsque je tente de reconvertir la TreeSet J'utilise devient un HashSet.

En théorie ma collection pourrait être fixée à un TreeSet (qui corrige le problème), mais je préfère configurer JAXB correctement et différer cette logique ailleurs. Comment puis-je dire à JAXB de construire un TreeSet à la place?

+0

J'ai partiellement répondu à ma propre question tout en l'écrivant: Puisque je dois préserver l'ordre naturel de mon ensemble, il aurait dû être un SortedSet en premier lieu. J'ai changé cela et le unmarshalling fonctionne correctement maintenant. J'aimerais toujours avoir des commentaires sur ma configuration, en particulier je dicterais plutôt l'implémentation de JAXB, plutôt que de me fier à la magie ... – seanhodges

Répondre

2

La meilleure façon de résoudre ce problème est pré-initialiser votre Set propriété au type de mise en œuvre appropriée, et votre JAXB implmentation (Metro, EclipseLink MOXy, Apache JaxMe, etc.) utilisera qu'au lieu de créer un nouveau jeu:

package forum7104810; 

import java.util.Set; 
import java.util.TreeSet; 

import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlElementWrapper; 
import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement(name="root") 
class MyParentClass { 

    // Initialize this property with an instance of the desired type. 
    private Set<MyFieldItem> items = new TreeSet<MyFieldItem>(); 

    public void setItems(Set<MyFieldItem> items) { 
    this.items = items; 
    } 

    @XmlElementWrapper(name="mylist") 
    @XmlElement(name="item") 
    public Set<MyFieldItem> getItems() { 
    return items; 
    } 

} 

Pour plus d'informations

+0

Je vais essayer ça ce soir, ça ressemble à une solution assez élégante si Ça marche. – seanhodges

+1

Cela fonctionnera certainement, pour plus d'informations voir: http://blog.bdoughan.com/2011/01/jaxb-and-choosing-list-implementation.html –

+0

Cela a fonctionné, bien que j'ai opté pour définir le champ comme SortedSet au lieu de cela, qui a eu le même effet. Merci de votre aide! – seanhodges