如何使用JAXB将缺失的元素反序列化为空对象

3
我正在使用Intellij-IDEA中的JAXB Maven插件(org.codehaus.mojo:jaxb2-maven-plugin:1.6)将给定的xsd文件生成为对象。该xsd非常大,包含许多类型,其中大多数类型是可选的。
目前,当我将XML unmarshal到对象时,缺少的元素将表示为null对象。
因此,例如,如果我尝试执行rootObject.getAccount().getAccountName(),但XML中根本没有Account元素,则会导致NullPointerException
我希望配置JAXB,在unmarshal到对象时完整地包括代表缺少元素的对象树。
这有可能吗?

元素真的缺失了吗?还是只有结束标签丢失了?例如,你得到了这样的元素 <a/>。 - Ken de Guzman
是的,输入的 XML 中缺少该元素。 - benji
1个回答

2

这实际上是不正确的,因为使用默认值填充的该属性与语义上为null的属性是不同的。因此,在对于缺少值的account属性上设置new Account()是不正确的。

如果您想简化代码,请考虑使用JAXB2 Fluent API插件。你可能会得到类似以下的代码:

rootObject.withAccount().getAccountName()

(隐式初始化账户。) 我不能完全确定它能否以这种方式工作,但值得一试。

更新

关于您的评论,有几点需要注意。

我看了您发布的链接并尝试在网上查找,但如果我理解正确,它主要用于填充对象中的值而不是读取它们。您发送的链接说:FluentApi插件为bean设置器提供方法链接。我正在寻找一种方法来避免在尝试访问嵌套类时检查空值。

您是正确的。但是,您特别提到了“解包完整的对象树以包括表示丢失元素的对象”。我的观点是,JAXB 填充这些缺失的属性是不正确的,但是可以这样做,而 Fluent API 插件是我知道的最接近易于使用的 API 的工具,适用于这种情况。但是,这并没有回答您的问题,因为可能目前还没有答案。

那里的评论大多建议要么默默忍受并沿着这条路检查空值,使用反射或仅捕获错误。出于性能考虑,我最终选择了第一种选项。

目前您可以做的最好的事情可能就是这样。这就是我一直在做的(检查null)。嗯,不太好,但也很平凡。

接下来,我思考了如何解决这个问题?

XJC 支持插件,它可以增强生成的代码。这是一个非常强大的工具,我用这些插件做了很多工作。但应该生成什么代码?在 Java 中应该是什么样子?

填充属性的默认值根本不正确。我认为这样做不会得到良好的结果。

rootObject.getAccount().getAccountName()之类的东西由于null而无法工作。那么在 Java 中会是什么样子呢?

我想到的最好的方法是一个接口,例如getValueByPath(String propertyPath),以便您可以执行以下操作:

rootObject.getValueByPath(`account.accountName`);
getValueByPath(String path) 可以由插件生成。可以生成代码来解决这样的path,而不需要使用反射。生成的代码将检查自己的属性,并返回目标值,或在其上调用 getValueByPath(...),如果未找到/null则返回null
但是这样做就无法自动完成,整个过程也会更容易出错。

我看了你发的链接并试图在网上查找,但如果我理解正确,它主要用于填充对象中的值而不是读取它们。你发送的链接说:_FluentApi插件为bean setter提供方法链接_。我正在寻找一种方法来避免在尝试访问嵌套类时检查null的方式。 - benji
我还发现了这个链接(https://dev59.com/IGkv5IYBdhLWcg3wvDNF),它似乎描述了同样的问题。那里的评论大多建议要么忍受并沿途检查null值,使用反射,或者只是捕获错误。出于性能考虑,我最终选择了第一种选项。但我希望jaxb可以以某种方式定义getter或unmarshaller,以便将null对象传播到整个层次结构中。 - benji

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接