首页 > 解决方案 > JAXB 在 ChildA 继承中引用 ChildB

问题描述

我正在尝试解组以下 xml:

<?xml version="1.0" encoding="UTF-8" ?>
<container>
    <childs>
        <child uuid="1" childB="3" attrA="specialAttrA1" />
        <child uuid="2" childB="4" attrA="specialAttrA2" />
        <child uuid="3" attrB="specialAttrB1" />
        <child uuid="4" attrB="specialAttrB2" />
    </childs>
</container>

据我所知,这种情况包含两个主要问题:

对象层次结构由 ChildA 和 ChildB 组成,它们是 Parent 的子类(参见下面的源代码)。

最后,除了引用“childB”为空之外,未编组的对象看起来不错。

我找不到这种情况的任何例子。调试下面的源问我为什么传递给适配器的 unmarshal-method 的 FlatParent 对象不包含 childB。

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Container {
    @XmlElementWrapper(name = "childs")
    @XmlElement(name = "child")
    private List<Parent> childs = new ArrayList<>();
}

@XmlRootElement
@XmlAccessorType(value = XmlAccessType.FIELD)
@XmlJavaTypeAdapter(value = ParentAdapter.class, type = Parent.class)
public abstract class Parent {
    @XmlID
    @XmlAttribute
    private String uuid;
}

@XmlRootElement
@XmlAccessorType(value = XmlAccessType.FIELD)
public class ChildA extends Parent{
    @XmlAttribute
    private String attrA;
    @XmlIDREF
    @XmlAttribute
    private ChildB childB;
}

@XmlRootElement
@XmlAccessorType(value = XmlAccessType.FIELD)
public class ChildB extends Parent{
    @XmlAttribute
    private String attrB;
}

对应的适配器如下所示:

public class ParentAdapter extends XmlAdapter<FlatParent, Parent> {
    public Parent unmarshal(FlatParent fp) {
        Parent p = null;
        if (fp != null){
            if (fp.getAttrA() != null){
                p = new ChildA();
                ((ChildA) p).setAttrA(fp.getAttrA());
                ((ChildA) p).setChildB(fp.getChildB());
            } else {
                p = new ChildB();
                ((ChildB) p).setAttrB(fp.getAttrB());
            }
            p.setUuid(fp.getUuid());
        }
        return null;
    }
...

}

以及包含的 FlatParent:

@XmlRootElement
@XmlAccessorType(value = XmlAccessType.FIELD)
public class FlatParent {
    @XmlID
    @XmlAttribute
    private String uuid;
    @XmlAttribute
    private String attrA;
    @XmlAttribute
    private String attrB;
    @XmlIDREF
    @XmlElement
    private ChildB childB;
}

完全在这里也是测试类的一部分:

@Test
public void testImportXml() throws JAXBException {
    JAXBContext jc = JAXBContext.newInstance(Container.class);
    Unmarshaller unmarshaller = jc.createUnmarshaller();
    Container cont = (Container) unmarshaller.unmarshal(new File(FILEPATH));

标签: javaxmlinheritancereferencejaxb

解决方案


我认为你有两个选择:

1,使用unmarshaller-listener,缺点是您必须阅读 XML 两次并在每个涉及的对象解组后手动更新您的引用

2,按原样读取您的XML,使用数字并在使用java bean映射器解组到另一个pojos后将它们转换,例如MapStruct(在mapstruct中,具有相同名称的字段自动映射,您可以在装饰器子类中进行此引用映射)


推荐阅读