当前位置:  开发笔记 > 编程语言 > 正文

JAXB继承,unmarshal到marshaled类的子类

如何解决《JAXB继承,unmarshal到marshaled类的子类》经验,为你挑选了4个好方法。

我正在使用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() ...
}

编组按预期工作.问题在于解组,Person尽管JAXBContext使用了子类的包名,它仍然是解组的ReceiverPerson.

JAXBContext jaxbContext = JAXBContext.newInstance(package name of ReceiverPerson);

我想要的是解散ReceiverPerson.我已经能够做到这一点的唯一方法是删除@XmlRootElementPerson.不幸的是,这样做可以防止Person被编组.这就好像JAXB从基类开始并向下运行,直到找到@XmlRootElement具有相应名称的第一个.我试着加入createPerson()该方法返回ReceiverPersonObjectFactory但这并不能帮助.



1> ivan_ivanovi..:

你正在使用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
}

我很确定,通过使用这个概念,您可以自己控制编组/解组过程(包括选择要构造的正确[sub | super]类型).


因为当问题具有赏金时,Stackoverflow会自动以最多票数作为答案来奖励回复.

2> Pascal Thive..:

以下代码段是使用绿灯进行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> 13ren..:

Subclass Person两次,一次用于接收器,一次用于发送者,并且只将XmlRootElement放在这些子类上(离开超类Person,没有XmlRootElement).请注意,发送方和接收方都共享相同的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合作].当继承层次结构中的多个类具有XmlRootElement批注时,它可以避免您注意到的问题.

这可以说是一种更简洁,更实用的方法,因为它将常见的数据模型分开,所以它根本不是"解决方法".



4> vocaro..:

创建一个自定义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();
    }
}

推荐阅读
k78283381
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有