2012-03-06 44 views
7

Tôi đang cố gắng sử dụng JAXB để hủy hợp nhất một số XML, nhưng tôi nhận được một trường hợp "Không thể tạo một thể hiện của ...". Tôi hiểu tại sao - nó đang cố gắng tạo ra một thể hiện của một lớp trừu tượng. Những gì tôi muốn là có nó làm cho một thể hiện của một lớp thực hiện cụ thể. Mục tiêu của tôi với điều này là phải kiểm tra lớp cụ thể trên các phương thức setter. Có lẽ "qux" là một giá trị baz hợp lệ cho BarImpl, nhưng BarImpl2 muốn làm điều gì đó khác.JAXB và lớp trừu tượng

Tôi đã tham gia bằng cách không chú thích Foo, nhưng nếu tôi không thanh toán, mọi thứ trở nên xấu xí.

import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlRootElement; 

import org.junit.Test; 


public class JAXBTest { 

    @Test 
    public void test() throws javax.xml.bind.JAXBException { 
     String xml = 
      "<foo>" + 
      " <bar>" + 
      " <baz>qux</baz>" + 
      " </bar>" + 
      "</foo>"; 

     javax.xml.bind.JAXBContext context = javax.xml.bind.JAXBContext.newInstance(
       FooImpl.class, 
       BarImpl.class 
     ); 

     javax.xml.bind.Unmarshaller unmarshaller = context.createUnmarshaller(); 

     unmarshaller.unmarshal(new java.io.StringReader(xml)); 
    } 

    @XmlRootElement(name="foo") 
    public static abstract class Foo { 
     @XmlElement(name="bar") 
     Bar bar; 
    } 

    @XmlRootElement(name="bar") 
    public static abstract class Bar { 
     @XmlElement(name="baz") 
     String baz; 
    } 

    public static class FooImpl extends Foo { } 
    public static class BarImpl extends Bar { } 
} 

Trả lời

14

Bạn có thể làm như sau:

JAXBTest

import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlElements; 
import javax.xml.bind.annotation.XmlRootElement; 
import javax.xml.bind.annotation.XmlTransient; 

import org.junit.Test; 


public class JAXBTest { 

    @Test 
    public void test() throws javax.xml.bind.JAXBException { 
     String xml = 
      "<foo>" + 
      " <bar>" + 
      " <baz>qux</baz>" + 
      " </bar>" + 
      "</foo>"; 

     javax.xml.bind.JAXBContext context = javax.xml.bind.JAXBContext.newInstance(
       FooImpl.class, 
       BarImpl.class 
     ); 

     javax.xml.bind.Unmarshaller unmarshaller = context.createUnmarshaller(); 

     unmarshaller.unmarshal(new java.io.StringReader(xml)); 
    } 

    @XmlTransient 
    public static abstract class Foo { 
     @XmlElements({ 
      @XmlElement(name="bar",type=BarImpl.class), 
      @XmlElement(name="bar",type=BarImpl2.class), 
     }) 
     Bar bar; 
    } 

    @XmlTransient 
    public static abstract class Bar { 
     @XmlElement(name="baz") 
     String baz; 
    } 

    @XmlRootElement(name="foo") 
    public static class FooImpl extends Foo { } 

    @XmlRootElement(name="bar") 
    public static class BarImpl extends Bar { } 

    public static class BarImpl2 extends Bar { } 
} 
+0

Một trong những điều nó thiếu là nếu tôi làm BarImpl2, bar (trong Foo) đã được đánh dấu là một BarImpl. –

+0

Tôi đã cập nhật câu trả lời của mình để sử dụng '@ XmlElements' để xử lý trường hợp sử dụng này. –

+0

Nó hoạt động! Sự khó chịu duy nhất hiện nay là người triển khai BarImpl2 cần phải thay đổi các chú thích trong Foo, nhưng nó chỉ là một sự khó chịu. –

Các vấn đề liên quan