Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XStream Alias of List root elements

I want to be able to alias the root list element depending upon what type of objects are contained in the list. For example, this is my current output:

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

And this is what I want it to look like:

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

I can do this at a global level by saying all lists should be aliased to coins, but I have a lot of different lists and this won't work. Any ideas on how to do this? Seems like it should be simple, but of course, it isn't.

EDIT: I should specify, I am trying to serialize objects to xml. I am using Spring 3 MVC as my web framework.

like image 738
efleming Avatar asked Sep 29 '10 17:09

efleming


3 Answers

Let's say you have a Coin class with a type attribute, as follows:

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

And you have a Coins class that constains a List of Coin:

@XStreamAlias("coins")
public class Coins{

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

Pay attention to the annotations. The List is Implicit and the Coins class will be shown as "coins".

The output will be:

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

It's not the same you asked for, but there is a reason.

At first, coin have only one attribute, but we are not sure if all objects you want to show do have only one attribute too. So, we need to tell which object attribute we are talking about.

You can also show the Coin attributes as XML Attributes, not fields. As follows:

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

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

Here is the output:

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

Hope it helps.

like image 147
pablosaraiva Avatar answered Nov 18 '22 12:11

pablosaraiva


This isn't an ideal solution, as it requires a separate wrapper class, but you could do something like this:

public class CoinResponse {

   private List<Coin> coinList;

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

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

And here's the ugly part:

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));

Basically, this is telling Xstream to use "coins" when converting the CoinResponse, and then don't use any name at all for the list itself.

like image 5
Greg Case Avatar answered Nov 18 '22 12:11

Greg Case


@XStreamAlias("coins")
public class Coins {
        @XStreamImplicit(itemFieldName="coin")
        List<String> coins = new ArrayList<String>();
}
like image 4
Bujji Avatar answered Nov 18 '22 11:11

Bujji