gpt4 book ai didi

java - JAXB 2.x : How to override an XmlElement annotation from parent class - Mission Impossible?

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:53:53 25 4
gpt4 key购买 nike

为什么这不可能?看起来很简单,但它的行为并不像预期的那样。

总结:A 类使用聚合的 DataA bean,而 B 类(A 类的子类)使用聚合的 DataB bean(而 DataB 扩展了 DataA)。

我编写了这些测试类来可视化和解释我的问题:

A 类:

package test;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement(name="root")
public class A {

private DataA source = new DataA();

@XmlElement(name="source")
public DataA getSource() {
return source;
}

public void setSource(DataA source) {
this.source = source;
}

}

及其 DataA 类(我使用了 FIELD 注释以便对所有字段进行编码):

package test;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;

@XmlAccessorType(XmlAccessType.FIELD)
public class DataA {

public String string1 = "1";
public String string2 = "2";

}

现在是 B 类(A 类的子类):我的目标是重用 A 的功能,并通过使用 DataB bean 重用 DataA bean 的属性:

package test;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement(name="root")
public class B extends A {

private DataB source = new DataB();

public DataB getSource() {
return this.source;
}

public void setSource(DataB source) {
this.source = source;
}

}

它对应的 DataB bean 如下所示:

package test;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;

@XmlAccessorType(XmlAccessType.FIELD)
public class DataB extends DataA {
public String string3 = "3";
}

现在,当我编码 A 类的实例时,它会给出以下输出:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<source>
<string1>1</string1>
<string2>2</string2>
</source>
</root>

当我编码 B 类的一个实例时,我得到了完全相同的结果:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<source>
<string1>1</string1>
<string2>2</string2>
</source>
</root>

但我预计 string3 也会被编码,但它只是写入 bean DataA 的属性!为什么?从 OOP 的角度考虑时,这并不是很直观。

当我也在 B 类上设置 @XmlElement 注释时...像这样:

@XmlElement
public DataB getSource() {
return this.source;
}

... 然后该属性被编码两次,因为它曾经被父类和子类注释过。这也是我不想要的:

现在的输出是:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<source xsi:type="dataB" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<string1>1</string1>
<string2>2</string2>
<string3>3</string3>
</source>
<source>
<string1>1</string1>
<string2>2</string2>
<string3>3</string3>
</source>
</root>

我期望从 JAXB 得到的结果是以下 XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<source>
<string1>1</string1>
<string2>2</string2>
<string3>3</string3>
</source>
</root>

关于如何调整 JAXB 以产生预期结果的任何提示?感谢您的任何反馈。

最佳答案

只是不要在类 B 上注释 source 属性。source 属性已映射到父类,不应再次映射到子类。由于您正在注释 get/set 方法,因此将在类 B 上调用适当的 get/set。

package test;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement(name="root")
public class B extends A {

private StringBuffer source = null;

public String getSource() {
return source.toString();
}

public void setSource(String source) {
this.source = new StringBuffer(source);
}
}

更新

Metro JAXB 中可能存在错误(引用实现)。当我使用 EclipseLink JAXB (MOXy) 运行这个更新的示例时我得到以下输出:

<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<source>
<string1>1</string1>
<string2>2</string2>
</source>
</root>
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="b">
<source xsi:type="dataB">
<string1>1</string1>
<string2>2</string2>
<string3>3</string3>
</source>
</root>

这可以用下面的代码重现:

package test;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;

public class Demo {

public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(A.class, B.class);

Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

A a = new A();
DataA da = new DataA();
da.string1 = "1";
da.string2 = "2";
a.setSource(da);
marshaller.marshal(a, System.out);

B b = new B();
DataB db = new DataB();
db.string1 = "1";
db.string2 = "2";
db.string3 = "3";
b.setSource(db);
marshaller.marshal(b, System.out);
}
}

要使用 MOXy 作为 JAXB 实现,您需要在模型包(测试)中提供一个名为 jaxb.properties 的文件,其中包含以下条目:

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

关于java - JAXB 2.x : How to override an XmlElement annotation from parent class - Mission Impossible?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4661263/

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