2010-09-29 5 views
11

Ich möchte das Root-Listenelement abhängig davon, welche Art von Objekten in der Liste enthalten sind, als Alias ​​verwenden können. Zum Beispiel ist dies meine aktuelle Ausgabe:XStream-Alias ​​von List-Wurzelelementen

<list> 
<coin>Gold</coin> 
<coin>Silver</coin> 
<coin>Bronze</coin> 
</list> 

Und das ist, was ich will es so aussehen:

<coins> 
<coin>Gold</coin> 
<coin>Silver</coin> 
<coin>Bronze</coin> 
</coins> 

Ich kann dies tun auf globaler Ebene mit den Worten: alle Listen aliased werden sollen, um Münzen, aber ich habe viele verschiedene Listen und das wird nicht funktionieren. Irgendwelche Ideen, wie man das macht? Scheint so, als sollte es einfach sein, aber natürlich nicht.

EDIT: Ich sollte angeben, ich versuche Objekte in XML zu serialisieren. Ich verwende Spring 3 MVC als mein Web-Framework.

Antwort

23

Angenommen, Sie haben eine Münze-Klasse mit einem type-Attribut haben, wie folgt:

@XStreamAlias("coin") 
public class Coin { 
    String type; 
} 

Und Sie haben eine Münzen-Klasse, die eine Liste der Münze constains:

@XStreamAlias("coins") 
public class Coins{ 

    @XStreamImplicit 
    List<Coin> coins = new ArrayList<Coin>(); 
} 

Achten Sie auf die Anmerkungen. Die Liste ist implizit und die Münzen-Klasse wird als "Münzen" angezeigt.

wird der Ausgang sein:

<coins> 
    <coin> 
    <type>Gold</type> 
    </coin> 
    <coin> 
    <type>Silver</type> 
    </coin> 
    <coin> 
    <type>Bronze</type> 
    </coin> 
</coins> 

Es ist nicht das gleiche Sie gefragt, aber es gibt einen Grund.

Zuerst haben Münzen nur ein Attribut, aber wir sind nicht sicher, ob alle Objekte, die Sie zeigen möchten, auch nur ein Attribut haben. Also müssen wir sagen, über welches Objektattribut wir sprechen.

Sie können die Coin-Attribute auch als XML-Attribute und nicht als Felder anzeigen. Wie folgt:

@XStreamAlias("coin") 
public class Coin { 
    @XStreamAsAttribute 
    String type; 

    Coin(String type) { 
     this.type = type; 
    } 
} 

Hier ist die Ausgabe:

<coins> 
    <coin type="Gold"/> 
    <coin type="Silver"/> 
    <coin type="Bronze"/> 
</coins> 

Hoffe, es hilft.

+0

Danke, das ist leider die einzige Möglichkeit, dies zu tun. Erstellen einer nutzlosen Wrapper-Klasse. Es gibt keine Option für '#alias (" Münzen ", Liste .class)' (Pseudocode). –

5

Dies ist keine ideale Lösung, da es eine separate Wrapper-Klasse erfordert, aber man kann so etwas tun:

public class CoinResponse { 

    private List<Coin> coinList; 

    public CoinResponse(List<Coin> coinList) { 
     this.coinList = coinList; 
    } 

    public List<Coin> getCoins() { 
     return this.coinList; 
    } 
} 

Und hier ist der hässliche Teil:

List<Coin> coins = Arrays.asList(new Coin(), new Coin(), new Coin()); 
CoinResponse response = new CoinResponse(coins); 

XStream xstream = new XStream(); 
xstream.alias("coins", CoinResponse.class); 
xstream.addImplicitCollection(CoinResponse.class, "coinList"); 

System.out.println(xstream.toXML(response)); 

Grundsätzlich Das sagt Xstream, dass es beim Konvertieren der CoinResponse "Coins" verwenden soll, und verwendet dann keinen Namen für die Liste.

+0

Ich habe gerade etwas bemerkt. Wenn Sie Arrays.asList() wie oben verwenden, funktioniert meine Methode nicht. Stattdessen müssen Sie immer eine ArrayList übergeben, oder der CoinResponse-Konstruktor sollte den Listenparameter in eine neue ArrayList() umbrechen. –

4
@XStreamAlias("coins") 
public class Coins { 
     @XStreamImplicit(itemFieldName="coin") 
     List<String> coins = new ArrayList<String>(); 
}