JAXB 2.x:如何从父类覆盖 XmlElement 注释 - 不可能的任务?
为什么这是不可能的?看起来很简单,但它的表现并不像预期的那样。
摘要: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 以产生预期结果? 感谢您的任何反馈。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
只是不要在类 B 上注释源属性。源属性已映射到父类上,不应再次映射到子类上。由于您正在注释 get/set 方法,因此将在类 B 上调用适当的 get/set。
更新
Metro JAXB(参考实现)。当我使用 EclipseLink JAXB (MOXy) 运行这个更新的示例时,我得到以下输出
:可以使用以下代码重现:
要使用 MOXy 作为 JAXB 实现,您需要在模型包(测试)中提供名为 jaxb.properties 的文件,其中包含以下条目:
Just don't annotate the source property on class B. The source property was mapped on the parent class and should not be mapped again on the child class. Since you are annotating the get/set methods the appropriate get/set will be called on class B.
UPDATE
There may be a bug in the Metro JAXB (reference implementation). When I run this updated example with EclipseLink JAXB (MOXy) I get the following output:
This can be reproduced with the following code:
To use MOXy as the JAXB implementation you need to supply a file named jaxb.properties in the model package (test) with the following entry:
你不需要使用 MOXy..
只需更改 B 类并使用 @XmlAlso 即可。
最后会写:
you don't need to use MOXy..
Just change the Class B and use @XmlAlso.
WILL FINALLY WRITE:
非常感谢布莱斯提供的所有这些提示。 MOXy 现在可以很好地与我的真实应用程序一起使用真实的豆子。好的!
我目前唯一的缺点是此配置代码中的最后一行不再起作用,因为 MOXy 当然使用另一个名称空间前缀映射机制。
你有这方面的指针吗?我搜索了 MOXy 文档并搜索了命名空间,但没有找到类似的内容。
Thanks a lot Blaise for all these hints. MOXy now works fine with my real application with real beans. nice!
The only drawback I currently have is that the last line in this configuration code does not work anymore because MOXy uses of course another namespace prefix mapping mechanism.
Do you have a pointer for this? I searched the MOXy documentation and search for namespace but nothing similar was found.
您可以使用此方法:
此映射对我有用。
You can use this method:
this mapping worked for me.