Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why my ArrayList is not marshalled with JAXB?

Tags:

java

xml

jaxb

Here is the use case:

@XmlRootElement
public class Book {
  public String title;
  public Book(String t) {
    this.title = t;
  }
}
@XmlRootElement
@XmlSeeAlso({Book.class})
public class Books extends ArrayList<Book> {
  public Books() {
    this.add(new Book("The Sign of the Four"));
  }
}

Then, I'm doing:

JAXBContext ctx = JAXBContext.newInstance(Books.class);
Marshaller msh = ctx.createMarshaller();
msh.marshal(new Books(), System.out);

This is what I see:

<?xml version="1.0"?>
<books/>

Where are my books? :)

like image 372
yegor256 Avatar asked Nov 11 '10 07:11

yegor256


People also ask

How does JAXB marshalling work?

In JAXB, marshalling involves parsing an XML content object tree and writing out an XML document that is an accurate representation of the original XML document, and is valid with respect the source schema. JAXB can marshal XML data to XML documents, SAX content handlers, and DOM nodes.

Is JAXB Unmarshaller thread safe?

A: The JAXB Specification currently does not address the thread safety of any of the runtime classes. In the case of the Oracle JAXB RI, the JAXBContext class is thread safe, but the Marshaller , Unmarshaller , and Validator classes are not thread safe.


2 Answers

The elements to be marshalled must be public, or have the XMLElement anotation. The ArrayList class and your class Books do not match any of these rules. You have to define a method to offer the Book values, and anotate it.

On your code, changing only your Books class adding a "self getter" method:

@XmlRootElement
@XmlSeeAlso({Book.class})
public class Books extends ArrayList<Book> {
  public Books() {
    this.add(new Book("The Sign of the Four"));
  }

  @XmlElement(name = "book")
  public List<Book> getBooks() {
    return this;
  }
}

when you run your marshalling code you'll get:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<books><book><title>The Sign of the Four</title></book></books>

(I added a line break for clarity's shake)

like image 60
Tomas Narros Avatar answered Nov 02 '22 16:11

Tomas Narros


I don't think you can easily marshall a List as is. Consider using another class to wrap the list in. The following works:

@XmlType
class Book {
    public String title;

    public Book() {
    }

    public Book(String t) {
        this.title = t;
    }
}

@XmlType
class Books extends ArrayList<Book> {
    public Books() {
        this.add(new Book("The Sign of the Four"));
    }
}

@XmlRootElement(name = "books")
class Wrapper {
    public Books book = new Books();
}

Used like the following:

JAXBContext ctx = JAXBContext.newInstance(Wrapper.class);
Marshaller msh = ctx.createMarshaller();
msh.marshal(new Wrapper(), System.out);

it produces this result:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<books><book><title>The Sign of the Four</title></book></books>
like image 28
musiKk Avatar answered Nov 02 '22 17:11

musiKk