Kon*_*kin 5 java jaxb xml-serialization java-7
我使用@XmlID和@XmlIDREF标记来引用另一个对象.即使使用继承的类,它在Java 6中也能正常工作.我创建的示例代码如下所示.基类使用的标签:
@XmlRootElement
@XmlAccessorType(FIELD)
public class Module {
Module() {}
@XmlIDREF
private Module other;
@XmlID
private String id;
public Module(String id, Module other) {
this.id = id;
this.other = other;
}
}
Run Code Online (Sandbox Code Playgroud)
继承类:
@XmlRootElement
public class TheModule extends Module {
TheModule() {}
private String feature;
public TheModule(String id, Module other, String feature) {
super(id, other);
this.feature = feature;
}
}
Run Code Online (Sandbox Code Playgroud)
这些类的容器:
@XmlRootElement
public class Script {
Script() {}
public Script(Collection<Module> modules) {
this.modules = modules;
}
@XmlElementWrapper
@XmlElementRef
Collection<Module> modules = new ArrayList<Module>();
}
Run Code Online (Sandbox Code Playgroud)
运行此示例代码时:
public class JaxbTest {
private Script createScript() {
Module m1 = new Module("Module1", null);
Module m2 = new TheModule("Module2", m1, "featured module");
Module m3 = new Module("Module3", m2);
return new Script(Arrays.asList(m1, m2, m3));
}
private String marshal(Script script) throws Exception {
JAXBContext context = JAXBContext.newInstance(Module.class, Script.class, TheModule.class);
Writer writer = new StringWriter();
context.createMarshaller().marshal(script, writer);
return writer.toString();
}
private void runTest() throws Exception {
Script script = createScript();
System.out.println(marshal(script));
}
public static void main(String[] args) throws Exception {
new JaxbTest().runTest();
}
}
Run Code Online (Sandbox Code Playgroud)
我在Java 6中收到XML:
<script>
<modules>
<module>
<id>Module1</id>
</module>
<theModule>
<other>Module1</other>
<id>Module2</id>
<feature>featured module</feature>
</theModule>
<module>
<other>Module2</other>
<id>Module3</id>
</module>
</modules>
</script>
Run Code Online (Sandbox Code Playgroud)
请注意,对m2(TheModule实例)的引用按预期序列化.但是当在Java 7(Jaxb 2.2.4-1)下运行相同的代码时,我收到:
<script>
<modules>
<module>
<id>Module1</id>
</module>
<theModule>
<other>Module1</other>
<id>Module2</id>
<feature>featured module</feature>
</theModule>
<module>
<other xsi:type="theModule" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<other>Module1</other>
<id>Module2</id>
<feature>featured module</feature>
</other>
<id>Module3</id>
</module>
</modules>
</script>
Run Code Online (Sandbox Code Playgroud)
所以你可以看到最新的JAXB @XmlIDREF继承模块不起作用!
这个答案是错误的。不要依赖它,而是阅读 的文档JAXBContext.newInstance(...),请参阅此答案和下面的评论。
我认为您将 JAXB 与以下行混淆了。
JAXBContext.newInstance(Module.class, Script.class, TheModule.class);
Run Code Online (Sandbox Code Playgroud)
您告诉它您想要序列化 XML类型Script和Module。JAXB 将以特殊TheModule方式处理后一种类型的对象,因为您已经提供了它的基类:它向它添加了一个区分属性。这样就可以在序列化的 XML 中区分这两种类型。
尝试仅提供Script和,所有Module模块的基类。
JAXBContext.newInstance(Module.class, Script.class);
Run Code Online (Sandbox Code Playgroud)
事实上,您可以Module完全省略。JAXB 将推断Script您尝试从上下文序列化的对象中的类型。
顺便说一句,这种行为与 Java 6 并不完全相关。它与正在使用的 JAXB 实现相关(好吧,好吧,我知道几乎是同一件事)。在我的项目中,我使用 JAXB 2.2.4-1,它也在 Java 6 和 7 中重现了当前的问题。
哦,还有一件事:您可以使用以下命令将格式化的 XML 发送到 ,而不是创建 aStringWriter并将对象编组到其中,然后将其内容发送到。System.outstdout
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(script, System.out);
Run Code Online (Sandbox Code Playgroud)
也许这可以(稍微)简化进一步的测试。
| 归档时间: |
|
| 查看次数: |
1750 次 |
| 最近记录: |