JAXB和抽象类 [英] JAXB and abstract classes

查看:101
本文介绍了JAXB和抽象类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用JAXB来解组某些XML,但我得到的是无法创建...的实例异常。我理解为什么 - 它试图创建一个抽象类的实例。我想要的是让它成为特定实现类的实例。我的目标是对setter方法进行特定于类的检查。也许qux是BarImpl的有效baz值,但是BarImpl2想要做其他事情。

I'm trying to use JAXB to unmarshall some XML, but I'm getting an "Unable to create an instance of..." exception. I understand why--it's trying to make an instance of an abstract class. What I want is to have it make an instance of a specific implementing class. My goal with this is to have class-specific checks on setter methods. Maybe "qux" is a valid baz value for BarImpl, but BarImpl2 wants to do something else.

我通过不注释Foo而得到了一部分,但是如果我unannotate bar,事情变得丑陋。

I got part of the way there by not annotating Foo, but if I unannotate bar, things get ugly.

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


推荐答案

您可以执行以下操作:

  • Annotation the impl classes with @XmlRootElement instead of the abstract classes.
  • Mark the abstract classes with @XmlTransient (see http://blog.bdoughan.com/2011/06/ignoring-inheritance-with-xmltransient.html)
  • Use @XmlElement(type=BarImpl.class) on the bar property to specify the concrete type (see http://blog.bdoughan.com/2011/05/jaxb-and-interface-fronted-models.html).

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

这篇关于JAXB和抽象类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆