JAXB的继承,解组到封送类的子类

我用JAXB来读写XML。我要的是一个基类JAXB的编组和继承的JAXB类解组。这是为了允许一个发送者的Java应用程序发送XML到另一个接收机的Java应用程序。发送者和接收者将共享JAXB库。我想接收到的XML解组到它扩展了通用的JAXB类接收器特定的JAXB类。 例如: 这是JAXB类,它由发送方。
@XmlRootElement(name="person")
public class Person {
 public String name;
 public int age;
}
这是接收特定的JAXB解组XML时。接收器类具有特定于接收机中的应用逻辑。
@XmlRootElement(name="person")
public class ReceiverPerson extends Person {
 public doReceiverSpecificStuff() ...
}
编组如预期般运作。问题是解组,它仍然要解组 Person尽管子类的包 ReceiverPerson
JAXBContext jaxbContext = JAXBContext.newInstance(package name of ReceiverPerson);
我想要的是来解读为 ReceiverPerson。我已经能够做到这一点的唯一方法是删除 @XmlRootElementPerson。不幸的是这样做防止 Person被封。这是因为如果JAXB开始于基类和它的工作方式,直到它找到优先个 @XmlRootElement用适当的我试过添加 createPerson()方法,它返回 ReceiverPersonObjectFactory但是这并没有帮助。

-------------------------------------------------------------------------------------------------------------------------
1. 你是JAXB 2.0吧? (因为JDK6) 还有一类:
javax.xml.bind.annotation.adapters.XmlAdapter
哪一个可以继承和覆盖
public abstract BoundType unmarshal(ValueType v) throws Exception;
public abstract ValueType marshal(BoundType v) throws Exception;
例如:
public class YourNiceAdapter
  extends XmlAdapter{
 @Override public Person unmarshal(ReceiverPerson v){
  return v;
 }
 @Override public ReceiverPerson marshal(Person v){
  return new ReceiverPerson(v); // you must provide such c-tor
 }
}
用法做了如下:
@Your_favorite_JAXB_Annotations_Go_Here
class SomeClass{
 @XmlJavaTypeAdapter(YourNiceAdapter.class)
 Person hello; // field to unmarshal
}
我敢肯定,这个概念你可以自己控制编组/解组过程(包括选择正确的[子|超]类型构造)。
2. 下面的代码片断是一个JUnit 4测试了绿灯:
@Test
public void testUnmarshallFromParentToChild() throws JAXBException {
 Person person = new Person();
 int age = 30;
 String name = "Foo";
 person.name = name;
 person.age= age;
 // Marshalling
 JAXBContext context = JAXBContext.newInstance(person.getClass());
 Marshaller marshaller = context.createMarshaller();
 StringWriter writer = new StringWriter();
 marshaller.marshal(person, writer);
 String outString = writer.toString();
 assertTrue(outString.contains("
最重要的部分是的 JAXBContext.newInstance(Class... classesToBeBound)方法对数据编出上下文:
 context = JAXBContext.newInstance(Person.class, RecieverPerson.class);
通过此调用,JAXB上指定的类的引用封闭,并将确认 RecieverPerson。该测试通过。如果你改变了顺序,你会得到一个 java.lang.ClassCastException(所以他们必须在这个顺序传递)。
3. 子人两次,一次为接收器和一次发送者,只有把这些subclassses(离开超 CodeGo.net, Person,没有注意,发送者和接收者双方共享的JAXB基类。
@XmlRootElement(name="person")
public class ReceiverPerson extends Person {
 // receiver specific code
}
@XmlRootElement(name="person")
public class SenderPerson extends Person {
 // sender specific code (if any)
}
// note: no @XmlRootElement here
public class Person {
 // data model + jaxb annotations here
}
[测试,并使用JAXB工作。它绕过你注意到这个问题,当多个类继承层次结构有注释。 这也可以说是一个整洁,更面向对象的方法,它分离了数据模型,所以它不是一个“解决方法”的说法。
4. 创建一个自定义的ObjectFactory解组期间实例化所需的类。例如:
JAXBContext context = JAXBContext.newInstance("com.whatever.mypackage");
Unmarshaller unmarshaller = context.createUnmarshaller();
unmarshaller.setProperty("com.sun.xml.internal.bind.ObjectFactory", new ReceiverPersonObjectFactory());
return unmarshaller;
public class ReceiverPersonObjectFactory extends ObjectFactory {
 public Person createPerson() {
  return new ReceiverPerson();
 }
}

5. 我不知道你为什么会想这样做...它似乎所有的安全并 考虑ReceiverPerson会发生什么事情有更多的实例变量...那么你会风与(我猜的)这些变量为null,0或false ...而如果空不允许或数必须大于0? 我想你可能想要做的是读取联系人,然后从构造一个新的ReceiverPerson(可能会提供一个构造函数接受一个Person)。

6. 既然你真的有两个独立的应用程序,他们编译不同版本的类的“人”-与不具有接收器的应用程序@XmlRootElement(name="person")Person。这不仅是丑陋的,但它违背了你想要的人的定义为发送者和接收者的可维护性。它的一个可取之处是,它的工作原理。


转载地址:http://codego.net/36754/

你可能感兴趣的:(Java)