我正在使用JAXB来读写XML . 我想要的是使用基本JAXB类进行编组,并使用继承的JAXB类进行解组 . 这是为了允许发送方Java应用程序将XML发送到另一个接收方Java应用程序 . 发送方和接收方将共享一个通用的JAXB库 . 我希望接收器将XML解组为特定于接收器的JAXB类,该类扩展了通用JAXB类 .
例:
这是发件人使用的常见JAXB类 .
@XmlRootElement(name="person")
public class Person {
public String name;
public int age;
}
这是解组XML时使用的特定于接收器的JAXB类 . 接收器类具有特定于接收器应用的逻辑 .
@XmlRootElement(name="person")
public class ReceiverPerson extends Person {
public doReceiverSpecificStuff() ...
}
编组按预期工作 . 问题在于解组,尽管JAXBContext使用了子类 ReceiverPerson
的包名,但仍然可以解组 Person
.
JAXBContext jaxbContext = JAXBContext.newInstance(package name of ReceiverPerson);
我想要的是解散 ReceiverPerson
. 我能够做到这一点的唯一方法是从 Person
删除 @XmlRootElement
. 不幸的是,这样做可以防止 Person
被编组 . 这就好像JAXB从基类开始并向下运行,直到找到具有相应名称的第一个 @XmlRootElement
. 我已经尝试添加一个 createPerson()
方法,它将 ReceiverPerson
返回到 ObjectFactory
,但这没有帮助 .
6 回答
你正在使用JAXB 2.0吗? (自JDK6起)
有一节课:
哪一个可以子类化,并覆盖以下方法:
例:
使用方法如下:
我很确定,通过使用这个概念,您可以自己控制编组/解组过程(包括选择要构造的正确[sub | super]类型) .
以下代码段是使用绿灯进行Junit 4测试的方法:
重要的部分是使用
JAXBContext.newInstance(Class... classesToBeBound)
方法进行解组上下文:通过此调用,JAXB将计算指定类的引用闭包,并将识别
RecieverPerson
. 测试通过 . 如果您更改参数顺序,您将获得java.lang.ClassCastException
(因此它们按此顺序传递 must ) .Subclass Person两次,一次用于receiver,一次用于sender,只将XmlRootElement放在这些子类上(留下超类,
Person
,没有XmlRootElement) . 请注意,发送方和接收方都共享相同的JAXB基类 .[经过测试并确认可与JAXB合作] . 当继承层次结构中的多个类具有XmlRootElement批注时,它可以避免您注意到的问题 .
这可以说是一种更简洁,更实用的方法,因为它将常见的数据模型分开,所以它根本不是“解决方法” .
创建一个自定义ObjectFactory以在解组期间实例化所需的类 . 例:
我不确定你为什么要这样做......对我来说似乎并不安全 .
考虑一下ReceiverPerson会发生什么情况会有额外的实例变量......那么你最终会得到(我猜)那些变量为null,0或false ......以及如果不允许null或者数字必须大于0 ?
我想你可能想要做的是在Person中读取然后从中构造一个新的ReceiverPerson(可能提供一个带有Person的构造函数) .
由于你真的有两个独立的应用程序,使用不同版本的类"Person"编译它们 - 接收器应用程序
Person
上没有@XmlRootElement(name="person")
. 这不仅是丑陋的,而且它对发送者和接收者使用相同的Person定义都会破坏你想要的可维护性 . 它的一个救赎功能是它有效 .