gpt4 book ai didi

java - JAXB 将 XML 解码为抽象类型的错误子类

转载 作者:太空宇宙 更新时间:2023-11-04 09:35:44 24 4
gpt4 key购买 nike

我有一个抽象类A,它有两个子类BCA 看起来像这样:

@XmlTransient
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "A", propOrder = {
"operation",
"origin",
})
@XmlSeeAlso({B.class, C.class})
public abstract class A {

@XmlElement(required = true)
protected Operation operation;

@XmlElement(required = true)
protected Origin origin;

// getters and setters
}

B:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "A") // root element is A for all subclasses
@XmlType(name = "B", propOrder = {
"operation",
"origin",
"b",
})
public class B extends A {

@XmlElement(required = true)
protected String b;

// getter and setter
}

C:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "A") // root element is A for all subclasses.
@XmlType(name = "C", propOrder = {
"operation",
"origin",
"c",
})
public class C extends A {

@XmlElement(required = true)
protected String c;

// getter and setter
}

如何创建 JAXB 上下文:

private static JAXBContext createJaxbContext() throws JAXBException {
if(jaxbContext == null) {
final ClassLoader classLoader = A.class.getClassLoader();
final String contextPath = A.class.getPackage().getName();
jaxbContext = JAXBContext.newInstance(contextPath, classLoader);
}
return jaxbContext;
}

当我传入符合抽象类 A 但具有属性 b 的 XML 时,我希望 JAXB 能够将其解码为 B 类型的对象(如果属性 c 存在,则对于 C 也是如此)。当前发生的情况是,它尝试将所有 XML 字符串解码为 C 并且仅将 C 解码,从而导致 ClassCastException。

我尝试将子类指定为根节点上的类型 - 即类似:

<A xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="C">
<operation id="123" action="insert"/>
<origin>
<environment>DEV</environment>
<instance>root</instance>
</origin>
<c>c value</c>
</A>

但这并不能解决问题。

我可能做错了什么?将不胜感激任何帮助:)

编辑:如果有帮助,这是用于解码的方法

public static A toA(String xml) throws Exception{
try {
final Unmarshaller jaxbUnmarshaller = getJaxbContext().createUnmarshaller();
final StringReader reader = new StringReader(xml);
return (A) jaxbUnmarshaller.unmarshal(reader);
} catch (JAXBException e) {
throw new Exception("Failed to unmarshal A " + "[" + e.toString() + "].");
}
}

这是我的 ObjectFactory:

@XmlRegistry
public class ObjectFactory {

private final static QName A_QNAME = new QName("", "A");

public ObjectFactory() {}

public B createB() {
return new B();
}

public C createC() {
return new C();
}

public Operation createOperation() {
return new Operation();
}

public Origin createOrigin() {
return new Origin();
}

public A createA(A value) {
return new JAXBElement<>(A_QNAME, A.class, null, value).getValue();
}
}

最佳答案

我有一个解决方案,但它使用组合而不是继承。我不确定您是否有理由需要延长类(class)。

我简化了 A 类,因此我不必为起源和操作创建类,但我相信您明白了这一点(如果没有,请告诉我):

@XmlAccessorType(XmlAccessType.FIELD)
public class A {

// operation and origin stay the same

@XmlElements({
@XmlElement(name = "b", type = B.class),
@XmlElement(name = "c", type = C.class),
})
protected Object bOrC;
}

B 类和 C 类看起来像这样:

@XmlAccessorType(XmlAccessType.FIELD)
public class B {

@XmlValue
private String value;
}

您可以拥有一个 B 和 C 都可以扩展的接口(interface),而不是在 A 类中使用 Object。

那么它会因为 <c> 而解码罚款。或<b>值:

<A xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!--<operation id="123" action="insert"/>-->
<!--<origin>-->
<!--<environment>DEV</environment>-->
<!--<instance>root</instance>-->
<!--</origin>-->
<c>c value</c>
</A>

关于java - JAXB 将 XML 解码为抽象类型的错误子类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56548281/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com