2010-11-11 5 views
14

Đây là trường hợp sử dụng:Tại sao ArrayList của tôi không phải là marshalled với 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")); 
    } 
} 

Sau đó, tôi đang làm:

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

Đây là những gì tôi thấy:

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

Đâu là những cuốn sách của tôi? :)

+0

Bạn không thể marshall 'ArrayList' (như các ngôn ngữ khác không biết ArrayList) nhưng bạn có thể marshall' List'. –

+0

The Elite Gentleman - Tôi không chắc ý bạn là gì. Không giống như các thư viện liên kết và tuần tự hóa XML khác, JAXB không bao gồm bất kỳ thứ gì XML cụ thể trong đầu ra. –

+0

Vincenzo - Bạn có cần mở rộng Sách ArrayList không? Cách tiếp cận chung là dành cho lớp Books để có một thuộc tính ArrayList. –

Trả lời

12

Các yếu tố để được marshalled phải công khai, hoặc có tiền gửi XMLElement. Lớp ArrayList và sách lớp của bạn không phù hợp với bất kỳ quy tắc nào trong số này. Bạn phải xác định một phương thức để cung cấp các giá trị Book, và anotate nó.

Mở mã của bạn, chỉ thay đổi lớp Sách của bạn thêm một "tự getter" phương pháp:

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

khi bạn chạy mã marshalling của bạn, bạn sẽ nhận được:

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

(Tôi đã thêm một ngắt dòng cho lắc rõ ràng)

+0

Lớp 'Sách' của tôi có' @ XmlRootElement', vì vậy nó "khớp với các quy tắc" ... – yegor256

+0

Có, nhưng nó không hiển thị thuộc tính công khai hoặc phương thức được chú thích để nhận các giá trị.Vì vậy, bạn sẽ phải wirte một phương pháp mới anotate nó, hoặc viết một lớp wrapper. Hãy thử mã tôi đề xuất bạn. Nó sẽ tạo ra XML dự kiến ​​của bạn. Như bạn thấy, tôi đã giữ anotations cấp lớp của bạn (đó là đúng), và thêm một getBooks (trả về cùng một thể hiện danh sách) phương pháp với một @XMLElement anotation. –

2

Tôi không nghĩ rằng bạn có thể dễ dàng sắp xếp một số List. Xem xét sử dụng một lớp khác để bọc các danh sách trong các công việc sau:.

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

Được sử dụng như sau:

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

nó tạo ra kết quả này:

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

Vâng, đây không phải là những gì tôi mong đợi để có được. Bạn có thể thay đổi ví dụ của mình để tạo ra ' ...'? – yegor256

+0

@Vincenzo: Tôi đã thay đổi nó cho phù hợp. Tôi thấy bạn đã chấp nhận câu trả lời khác. Đó là một chút ngắn hơn nhưng theo ý kiến ​​của tôi một chút lạ. Một tài liệu XML luôn có một phần tử gốc duy nhất. Marshalling một 'List' trực tiếp là một chút trái với những gì tôi mong đợi. – musiKk

0

Như @Blaise và @musiKk đã chỉ ra, sẽ tốt hơn nếu chỉ cần có một Danh sách sách và cho phép Sách trở thành phần tử gốc thực sự. Tôi sẽ không xem xét việc mở rộng của ArrayList một thủ tục chấp nhận được trong mã của riêng tôi.