tags:

views:

73

answers:

1

Let's say I've got my domain objects laid out so the XML looks like this:

<account id="1">
  <name>Dan</name>
  <friends>
    <friend id="2">
      <name>RJ</name>
    </friend>
    <friend id="3">
      <name>George</name>
    </friend>
  </friends>
</account>

My domain object:

@XmlRootElement
public class Account {
    @XmlAttribute
    public Long id;
    public String name;

    @XmlElementWrapper(name = "friends")
    @XmlElement(name = "friend")
    public List<Account> friends;
}

Is there an easy way to configure JAXB to render only to a depth of 2? Meaning, I'd like my XML to look like this:

<account id="1">
    <name>Dan</name>
    <friends>
        <friend id="2" />
        <friend id="3" />
    </friends>
</account>
A: 

You can do this using an XmlJavaTypeAdapter.

Change Account as follows:

@XmlRootElement
public class Account {
    @XmlAttribute
    public Long id;
    public String name;

    @XmlElementWrapper(name = "friends")
    @XmlElement(name = "friend")
    @XmlJavaTypeAdapter( value = AccountAdapter.class )
    public List<Account> friends;
}

AccountAdapter.java:

public class AccountAdapter extends XmlAdapter<AccountRef, Account>
{
    @Override
    public AccountRef marshal(Account v) throws Exception 
    {   
        AccountRef ref = new AccountRef();
        ref.id = v.id;
        return ref;
    }

    @Override
    public Account unmarshal(AccountRef v) throws Exception 
    {
        // Implement if you need to deserialize
    }
}

AccountRef.java:

@XmlRootElement
public class AccountRef 
{ 
    @XmlAttribute
    public Long id;
}
mtpettyp
Have you teted this? I'm fairly sure this won't work, `XmlJavaTypeAdapter` can only handle scalar string values, not whole XML elements, even if the class signature suggests otherwise.
skaffman
@skaffman - yes I've tested it (though I noticed that I forgot to included the definition of AccountRef - I've updated my answer). The key is that XMLJavaTypeAdapter allows you to not only serialize a class that JAXB doesn't know about but also change how a class is serialized on a per-field basis. Here I'm creating a new class which serializes just the id field of an Account.
mtpettyp