2012-03-06 13 views
7

Bazı XML'leri unmarshall için JAXB'yi kullanmaya çalışıyorum, ancak "Bir örnek oluşturulamıyor ..." istisnası alıyorum. Nedenini anlıyorum - soyut bir sınıfın örneğini oluşturmaya çalışıyor. İstediğim şey, belirli bir uygulama sınıfının bir örneğini yapmaktır. Amacım, setter yöntemlerinde sınıfa özgü kontroller yapmaktır. Belki "qux", BarImpl için geçerli bir temel değerdir, ancak BarImpl2 başka bir şey yapmak ister.JAXB ve soyut sınıflar

Foo'yu not etmeyerek oraya yol aldım, ama eğer çubuğu boşaltırsam işler çirkinleşir.

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 { } 
} 

cevap

14

Aşağıdaki yapabilirdi:

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

Tek eksik bir şey yaparsanız BarImpl2, (Foo) çubuğu zaten BarImpl olarak işaretlenmiş olmasıdır. –

+0

Bu kullanım durumunu işlemek için '@ XmlElements' kullanmak için cevabımı güncelledim. –

+0

Çalıştı! Şu andaki tek sıkıntı, BarImpl2'nin uygulayıcısının Foo'daki ek açıklamaları değiştirmesi gerektiğidir, ancak bu sadece bir sıkıntıdır. –