Java JAXB:反序列化扩展类a的类B时出现问题 请考虑以下例子:

Java JAXB:反序列化扩展类a的类B时出现问题 请考虑以下例子:,java,constructor,jaxb,adapter,unmarshalling,Java,Constructor,Jaxb,Adapter,Unmarshalling,有一个ClassA和一个ClassB扩展了它。我现在的问题是,我必须从xml文件中解组一个ClassB。请注意,ClassA无法更改,因为它不在我的控制之下 本例中注意到几个问题: 主要问题是ClassA没有默认的无参数构造函数,这是没有适配器的JAXB所需要的。因此,我实现了MyAdapter,它将ClassB映射到简单类ValB,JAXB可以毫无问题地处理该类 主要问题是如何让JAXB使用这个适配器?无论是在类级别定义@XmlJavaTypeAdapter,还是将适配器注册到解组器,都无法做

有一个ClassA和一个ClassB扩展了它。我现在的问题是,我必须从xml文件中解组一个ClassB。请注意,ClassA无法更改,因为它不在我的控制之下

本例中注意到几个问题:

主要问题是ClassA没有默认的无参数构造函数,这是没有适配器的JAXB所需要的。因此,我实现了MyAdapter,它将ClassB映射到简单类ValB,JAXB可以毫无问题地处理该类

主要问题是如何让JAXB使用这个适配器?无论是在类级别定义@XmlJavaTypeAdapter,还是将适配器注册到解组器,都无法做到这一点

有人知道如何让JAXB使用MyAdapter,以便解组器返回一个属于ClassA实例的对象吗

public class JaxbTest {

    public static abstract class ClassA {
        public ClassA(String id) {
        }
    }

    @XmlRootElement
    @XmlJavaTypeAdapter(MyAdapter.class) // does not have an effect
    public static class ClassB extends ClassA {

        public String text;

        public ClassB() {
            super("");
        }
    }

    public static class ValB {
        public String text;
    }

    public static class MyAdapter extends XmlAdapter<ValB, ClassB> {

        @Override
        public ClassB unmarshal(ValB v) throws Exception {
            ClassB b = new ClassB();
            b.text = v.text;
            return b;
        }

        @Override
        public ValB marshal(ClassB v) throws Exception {
            ValB b = new ValB();
            b.text = v.text;
            return b;
        }

    }

    public static void main(String[] args) {
        try {
            JAXBContext context = JAXBContext.newInstance(ClassB.class);
            Unmarshaller unmarshaller = context.createUnmarshaller();
            unmarshaller.setAdapter(new MyAdapter()); // does not have an effect
            ClassA a = (ClassA) unmarshaller.unmarshal(new File("test.xml"));
            // do somthing with a
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
公共类JaxbTest{
公共静态抽象类ClassA{
公共类A(字符串id){
}
}
@XmlRootElement
@XmlJavaTypeAdapter(MyAdapter.class)//没有效果
公共静态类ClassB扩展了ClassA{
公共字符串文本;
公共类别B(){
超级(“”);
}
}
公共静态类ValB{
公共字符串文本;
}
公共静态类MyAdapter扩展了XmlAdapter{
@凌驾
公共类B解组(ValB v)引发异常{
ClassB=新的ClassB();
b、 text=v.text;
返回b;
}
@凌驾
公共ValB封送处理(ClassB v)引发异常{
ValB=新的ValB();
b、 text=v.text;
返回b;
}
}
公共静态void main(字符串[]args){
试一试{
JAXBContext context=JAXBContext.newInstance(ClassB.class);
Unmarshaller Unmarshaller=context.createUnmarshaller();
unmarshaller.setAdapter(新的MyAdapter());//没有效果
ClassA=(ClassA)unmarshaller.unmarshal(新文件(“test.xml”);
//用手指做某事
}捕获(例外e){
e、 printStackTrace();
}
}
}

顺便说一句:不要把代码看得太严肃——这只是一个演示问题的示例。我知道ClassAClassB的定义并不是很有用

更新


我们已经在即将发布的2.2.0版本中解决了这个问题(请参阅)。在此版本中,将不会检查抽象类的无参数构造函数

从12月18日开始,可以在此处获得具有此修复程序的预发布版本:

解决方法

这就是@XmlTransient注释的用途。如果可能,请执行以下操作:

@XmlTransient
public static abstract class ClassA {
    public ClassA(String id) {
    }
}
如果不能直接注释ClassA,您可以利用扩展来完成这项工作。MOXy允许您将JAXB元数据指定为XML文件。当您无法修改模型类时,这非常有用:

下面是一些解释@XmlAdapter的文章:


这两篇文章都不同,因为不可变对象是封装类的一个字段——在我的示例中并非如此。感谢您提供的信息,即使我打算使用JRE附带的JAXB版本。你的答案中最有趣的部分是莫西也有同样的错误。这可能是JAXB规范之外的情况,或者MOXy基于与SUN/Oracle实现相同的源代码?代码库是完全独立的。两组都决定对所有类进行无参数检查。至少现在在EclipseLink JAXB(MOXy)中我们已经修复了它。感谢您识别这个问题。我们已经在即将发布的EclipseLink JAXB(MOXy)版本中解决了这个问题。在此版本中,不需要对示例进行代码更改: