gpt4 book ai didi

java unmarshalling - NULL 值或缺少标记?

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

我在一个由解码器设置的类中有一个可为空的字段:

@XmlElement(name = "value", nillable = true)
private BigDecimal valueVariable;

我的问题是我无法判断 xml 元素是否已被省略或设置为 nil:

一个。元素 <value/> XML 文件中缺少它,因此它不是必需的。
=> (valueVariable == null) 为真

B. XML 文件包含 <value xsi:nil="true"/>
=> (valueVariable == null) 为真

如果值为 xsi:nil,我如何判断一个非字符串变量?还是标签丢失了?

更新您可以看到 2 个好的解决方案,我更喜欢其中一个,但另一个也可以!

最佳答案

JAXB (JSR-222) 实现可以将 null 表示为不存在的节点或基于 @XmlElement 上的 nillable 设置的可空元素>。当您需要同时支持两者或区分两者时,您可以利用 JAXBElement

Java 模型

JAXBElement 类型的字段/属性使用 @XmlElementRef 注释进行映射。这对应于用 @XmlRegistry 注释的类上的 @XmlElementDecl 注释。

import java.math.BigDecimal;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {

@XmlElementRef(name="foo")
JAXBElement<BigDecimal> foo;

@XmlElementRef(name="bar")
JAXBElement<BigDecimal> bar;

@XmlElementRef(name="baz")
JAXBElement<BigDecimal> baz;

}

对象工厂

import java.math.BigDecimal;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
import javax.xml.namespace.QName;

@XmlRegistry
public class ObjectFactory {

@XmlElementDecl(name = "foo")
public JAXBElement<BigDecimal> createFoo(BigDecimal value) {
return new JAXBElement<BigDecimal>(new QName("foo"), BigDecimal.class, value);
}

@XmlElementDecl(name = "bar")
public JAXBElement<BigDecimal> createBar(BigDecimal value) {
return new JAXBElement<BigDecimal>(new QName("bar"), BigDecimal.class, value);
}

@XmlElementDecl(name = "baz")
public JAXBElement<BigDecimal> createBaz(BigDecimal value) {
return new JAXBElement<BigDecimal>(new QName("baz"), BigDecimal.class, value);
}

}

演示代码

输入.xml

<?xml version="1.0" encoding="UTF-8"?>
<root>
<bar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
<baz>123.456</baz>
</root>

演示

下面是一些演示代码,您可以运行它来证明一切正常。请注意 JAXBIntrospector 如何在必要时用于获取展开 JAXBElement 的实际值。

import java.io.File;
import java.math.BigDecimal;
import javax.xml.bind.*;

public class Demo {

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

Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum18440987/input.xml");
Root root = (Root) unmarshaller.unmarshal(xml);

nullOrAbsent("foo", root.foo);
nullOrAbsent("bar", root.bar);
nullOrAbsent("baz", root.baz);

Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}

private static void nullOrAbsent(String property, JAXBElement<BigDecimal> value) {
System.out.print(property);
if(null == value) {
System.out.print(": ABSENT - ");
} else if(value.isNil()) {
System.out.print(": NIL - ");
} else {
System.out.print(": VALUE - ");
}
System.out.println(JAXBIntrospector.getValue(value));
}

}

输出

foo:  ABSENT - null
bar: NIL - null
baz: VALUE - 123.456
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<bar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
<baz>123.456</baz>
</root>

更新

如果您想维护现有的 get/set 方法,那么您可以像我在这个答案中那样保留字段访问权限,并将您的访问器方法更改为如下所示:

public BigDecimal getBar() {
if(null == bar) {
return null;
}
return bar.getValue();
}

public void setBar(BigDecimal bar) {
if(null == this.bar) {
this.bar = new JAXBElement<BigDecimal>(new QName("bar"), BigDecimal.class, bar);
} else {
this.bar.setValue(bar);
}
}

此外,您可以添加一个 isSet 方法来查看该值是否已设置。

public boolean isSetBar() {
return null != bar;
}

此方法不要求您有权访问 Unmarshaller。为确保选择 ObjectFactory,您可以使用 @XmlSeeAlso 注释从您的域类之一引用它。

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso(ObjectFactory.class)
public class Root {

关于java unmarshalling - NULL 值或缺少标记?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18440987/

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