简体   繁体   English

如何使用JAXB将缺少的元素解组为空对象

[英]How to unmarshal missing elements into empty objects using JAXB

I am using JAXB Maven plugin in Intellij-IDEA (org.codehaus.mojo:jaxb2-maven-plugin:1.6) to generate a given xsd file to objects. 我在Intellij-IDEA(org.codehaus.mojo:jaxb2-maven-plugin:1.6)中使用JAXB Maven插件来生成给定对象的xsd文件。 The xsd is pretty large and contains many types, most of which are optional. xsd非常大,包含许多类型,其中大多数是可选的。

Right now when I unmarshal an XML to objects, missing elements are represented as null objects. 现在,当我将XML解组为对象时,缺少的元素表示为空对象。

So for example, if I am trying to do rootObject.getAccount().getAccountName() but the Account element is missing altogether from the XML, I get a NullPointerException 因此,例如,如果我尝试执行rootObject.getAccount().getAccountName()但是从XML中完全丢失了Account元素,我得到一个NullPointerException

I would like to configure JAXB to unmarshal the full object tree to include those representing missing elements. 我想配置JAXB来解组整个对象树以包含那些表示缺少元素的对象树。

Is this possible? 这可能吗?

This would be actually incorrect, as null property is semantically different from this property stubbed with some default value. 这实际上是不正确的,因为null属性在语义上与这个以某个默认值存根的属性不同。 So setting some new Account() to account property for a missing value would not be correct. 因此,将一些new Account()设置为account属性以获取缺失值将是不正确的。

If you want to simplify your code, consider using JAXB2 Fluent API plugin . 如果要简化代码,请考虑使用JAXB2 Fluent API插件 You'll be probably able get code like: 你可能会得到如下代码:

rootObject.withAccount().getAccountName()

(Implicitly initializes account .) I am not 100% sure if it will work that way, but definitely worth giving it a try. (隐含地初始化account 。)我不是100%确定它是否会以这种方式工作,但绝对值得尝试一下。

Update 更新

A few notes on your comments. 关于你的意见的几点说明。

I looked at the link you've posted and tried to look it up online but if I understand correctly, it is mostly used for populating values in the objects rather than reading them. 我查看了你发布的链接并尝试在线查找,但如果我理解正确,它主要用于填充对象中的值而不是读取它们。 The link you sent says: The FluentApi plugin provides Method Chaining for bean setters. 您发送的链接说:FluentApi插件为bean setter提供Method Chaining。 I was looking for a way to somehow avoid checking for nulls when trying to access nested classes. 我正在寻找一种方法以某种方式避免在尝试访问嵌套类时检查空值。

You are correct. 你是对的。 However you said specifically "unmarshal the full object tree to include those representing missing elements" . 但是你特别说“解组完整的对象树以包含代表缺失元素的那些” My point is, it would be incorrect for JAXB to fill in these missing properties, but you can do this and the Fluent API plugin is the closes I would know to an easy-to-use API for this case. 我的观点是,JAXB填写这些缺失的属性是不正确的,但可以这样做,而Fluent API插件是我对一个易于使用的API知道的关闭。 But this does not answer your question as, probably, there is no answer at the moment. 但这并没有回答你的问题,因为可能目前没有答案。

The comments there mostly suggest to either suck it up and check for null values along the way, use reflection, or just catch the error. 那里的评论大多建议要么吸收它并检查沿途的空值,使用反射,或者只是捕获错误。 I ended up going with the first option for performance considerations. 我最后选择了第一个性能考虑因素。

Probably the best thing you can do at the moment. 可能是目前你能做的最好的事情。 This is what I do (checking for null s) all the time. 这就是我一直在做的(检查null s)。 Well, not quite nice, but also quite trivial. 嗯,不太好,但也很琐碎。

Next, I though a bit on how could this be solved at all? 接下来,我有点想知道如何解决这个问题?

XJC supports plugins which can augment the generated code. XJC支持可以增加生成代码的插件 This is a very powerful tool, I did a great lot with these plugins. 这是一个非常强大的工具,我用这些插件做了很多。 But what code should be generated? 但是应该生成什么代码? How should it look like in Java? 它应该如何在Java中看起来像?

Filling properties with default values is simply not correct. 使用默认值填充属性是不正确的。 I think gooing this way will not lead to good results. 我认为这样做不会带来好结果。

Something like rootObject.getAccount().getAccountName() won't work due to null s. 由于null s, rootObject.getAccount().getAccountName()类的东西rootObject.getAccount().getAccountName() So how would it look like in Java? 那么在Java中它会是什么样子?

The best thing that came to my mind is a interface like getValueByPath(String propertyPath) so that you could do something like: 我想到的最好的事情是像getValueByPath(String propertyPath)这样的接口,这样你就可以做类似的事情:

rootObject.getValueByPath(`account.accountName`);

The getValueByPath(String path) could be generated by a plugin. getValueByPath(String path)可以由插件生成。 It is possible to generate code which would resolve such path s without any reflection. 可以生成将在没有任何反射的情况下解析这种path的代码。 The generated code would check for own properties and either return the target value, or call getValueByPath(...) on it or return null if not found/ null . 生成的代码会检查自己的属性,要么返回目标值,或致电getValueByPath(...)上,或返回null ,如果未找到/ null

But then you won't have autocompletion and the whole thing would be much more error prone. 但是你不会有自动完成,整个事情会更容易出错。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM