简体   繁体   中英

JAXB Unmarshall to List

I am trying to unmarshall this XML to Java objects, a Customer object containing a List of EmailAdresses.

<customer>
 <emailAddresses>janed@example.com</emailAddresses>
 <emailAddresses>jdoe@example.org</emailAddresses>
</customer>

Having an issue with the list, I get the correct number of list items (2), but the value of the emailAddresses tag is null

Customer.java

@XmlRootElement( name = "customer" )
public class Customer
{
    private List<EmailAddress> emailAddresses;

    public Customer()
    {
        emailAddresses = new ArrayList<EmailAddress>();
    }

    public List<EmailAddress> getEmailAddresses()
    {
        return emailAddresses;
    }

    public void setEmailAddresses( List<EmailAddress> emailAddresses )
    {
        this.emailAddresses = emailAddresses;
    }
}

EmailAddress.java

public class EmailAddress
{
    private String emailAddresses;

    public String getEmailAddresses()
    {
        return emailAddresses;
    }

        public void setEmailAddresses( String emailAddresses )
    {
        this.emailAddresses = emailAddresses;
    }
}

Failing Unit Test

@Test
public void shouldDeserialiseCusomerXMLToObject() throws JAXBException
{
    String xml = "<customer>"
            + "    <emailAddresses>janed@example.com</emailAddresses>"
            + "    <emailAddresses>jdoe@example.org</emailAddresses>"
            + "</customer>";

    JAXBContext jaxbContext = JAXBContext.newInstance( Customer.class );
    Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();

    StringReader reader = new StringReader( xml );
    Customer msg = ( Customer ) jaxbUnmarshaller.unmarshal( reader );

    // This passes, I have 2 emailAddresses
    assertEquals( 2, msg.getEmailAddresses().size() );

    // This fails, I have a null pointer instead of the email address
    assertEquals( "janed@example.com", msg.getEmailAddresses().get( 0 ).getEmailAddresses() );
}

The emailAddresses field of EmailAddress is by default treated as a subelement, expecting the XML to be:

<customer>
    <emailAddresses>
        <emailAddresses>janed@example.com</emailAddresses>
    </emailAddresses>
    <emailAddresses>
        <emailAddresses>jdoe@example.org</emailAddresses>
    </emailAddresses>
</customer>

Since your outer <emailAddresses> element doesn't contain an inner <emailAddresses> element, the field is never assigned.

You want the emailAddresses field of EmailAddress to be the value of the (outer) <emailAddresses> element, so you have to tell JAXB that, by specifying the @XmlValue annotation:

@XmlValue
public String getEmailAddresses()
{
    return emailAddresses;
}

The @XmlValue annotation is especially useful when combined with @XmlAttribute , to support XML like this:

<Person sex="male" age="25">John Doe</Person>

Where class would then be:

public class Person {
    public enum Sex {
        @XmlEnumValue("male")   MALE,
        @XmlEnumValue("female") FEMALE,
    }
    @XmlAttribute
    private Sex sex;
    @XmlAttribute
    private int age;
    @Value
    private String name;
}

You have a level too many of email addresses.

If you should change the list of email addresses to a list of strings, like

@XmlRootElement( name = "customer" )
public class Customer
{
    private List<String> emailAddresses;

    public Customer()
    {
        emailAddresses = new ArrayList<String>();
    }

    public List<String> getEmailAddresses()
    {
        return emailAddresses;
    }

    public void setEmailAddresses( List<String> emailAddresses )
    {
        this.emailAddresses = emailAddresses;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM