2010-11-11 10 views
14

Aquí es el caso de uso:¿Por qué mi ArrayList no está coordinado con JAXB?

@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")); 
    } 
} 

Entonces, estoy haciendo:

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

Esto es lo que veo:

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

¿Dónde están mis libros? :)

+0

No puede ejecutar 'ArrayList' (ya que otros lenguajes no conocen ArrayList) pero puede usar' List'. –

+0

The Elite Gentleman - No estoy seguro de lo que quieres decir. A diferencia de otras bibliotecas de unión y serialización XML, JAXB no incluye nada XML específico en el resultado. –

+0

Vincenzo - ¿Necesita que los Libros amplíen ArrayList? El enfoque común es que la clase Books tenga una propiedad ArrayList. –

Respuesta

12

Los elementos que se marshalled debe ser público o tener la anotación XMLElement. La clase ArrayList y los libros de su clase no coinciden con ninguna de estas reglas. Debe definir un método para ofrecer los valores del Libro y anotarlo.

En su código, cambiando sólo la clase de libros adición de un método de "auto getter":

@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; 
    } 
} 

cuando se ejecuta el código de clasificación se obtendrá:

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

(He añadido una salto de línea para agitar la claridad)

+0

Mi clase 'Books' tiene' @ XmlRootElement', por lo que "coincide con las reglas" ... – yegor256

+0

Sí, pero no presenta un atributo público o un método anotado para obtener los valores.Entonces tendrá que crear un nuevo método y anotarlo, o escribir una clase contenedora. Prueba el código que te propuse. Generará su XML esperado. Como puede ver, he conservado las anotaciones de su nivel de clase (que son correctas) y he agregado un método getBooks (que devuelve la misma instancia de lista) con una anotación @XMLElement. –

2

No creo que pueda ordenar fácilmente un List como está. Considere el uso de otra clase para envolver la lista en las siguientes obras:.

@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(); 
} 

utilizarse como las siguientes:

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

que produce este resultado:

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

Bueno, esto no es exactamente lo que espero obtener. ¿Puede cambiar su ejemplo para producir ' ...'? – yegor256

+0

@Vincenzo: Lo cambié en consecuencia. Veo que ya aceptaste la otra respuesta. Es un poco más corto, pero en mi opinión un poco extraño. Un documento XML siempre tiene un único elemento raíz. Alinear una 'Lista' directamente es un poco contrario a lo que yo esperaría. – musiKk

0

Como @Blaise y @musiKk han señalado, sería mejor simplemente tener una Lista de libros en libros, y permitir que Libros sea el verdadero elemento raíz. No consideraría la extensión de ArrayList un procedimiento aceptable en mi propio código.

Cuestiones relacionadas