草庐IT

java unmarshalling - NULL 值或缺少标记?

coder 2024-03-19 原文

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

@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/

有关java unmarshalling - NULL 值或缺少标记?的更多相关文章

  1. "\0"null 的 Ruby 测试? - 2

    我在破坏脚本的字符串中出现了一些奇怪的字符。据我所知,通过putbadstring到控制台,它们是"\0\0\0\0"。我想对此进行测试,以便我可以忽略它们...但是如何呢?以为这就是blank?和empty?的用途?!?:>badstring="\0"=>"\u0000">badstring.blank?NoMethodError:undefinedmethod`blank?'for"\u0000":Stringfrom(irb):97from/Users/meltemi/.rvm/rubies/ruby-2.0.0-p195/bin/irb:16:in`'>badstring.em

  2. ruby-on-rails - 使用 gmaps4rails 动态加载谷歌地图标记 - 2

    如何只加载map边界内的标记gmaps4rails?当然,在平移和/或缩放后加载新的。与此直接相关的是,如何获取map的当前边界和缩放级别? 最佳答案 我是这样做的,我只在用户完成平移或缩放后替换标记,如果您需要不同的行为,请使用不同的事件监听器:在你看来(index.html.erb):{"zoom"=>15,"auto_adjust"=>false,"detect_location"=>true,"center_on_user"=>true}},false,true)%>在View的底部添加:functiongmaps4rail

  3. ruby-on-rails - 将 Ruby 代码和文字标记与 Haml 混合 - 2

    如何用HAML编写这个ERB:#OR我可以:=some_ruby_code+":"#and=some_ruby_code%br但我不想在这里连接,我想将它写成内联:(=some_ruby_code):#and(=some_ruby_code)%br 最佳答案 =some_ruby_code+":"-#and=some_ruby_code+""编辑1:我不确定您在寻找什么。你想要其中之一吗?==#{some_ruby_code}:-#and==#{some_ruby_code}或==#{some_ruby_code}:-#and=so

  4. ruby - 如何在 Chef 中使用 Ruby 标记 EC2 实例? - 2

    我正在尝试与Chef一起启动EC2实例。一切都运行良好,但Chef似乎无法标记实例。我错过了什么吗?否则,实现此目标的首选Ruby库是什么?我可以在不需要额外gem的情况下做到吗?谢谢 最佳答案 knife-ec2Gem的0.5.12版支持在创建时使用--tags选项标记EC2实例。knifeec2servercreate[...youroptions...]--tagsTag=Value 关于ruby-如何在Chef中使用Ruby标记EC2实例?,我们在StackOverflow上找到

  5. ruby-on-rails - 如果没有可用标签,则运行标记规范或全部 - 2

    我将guard与rspec和cucumber一起使用。要连续运行选定的规范,我只需使用focus标记来确定我要处理的内容。但问题是,如果没有带有该标签的规范,我想运行所有规范。我该怎么做?注意::我知道所有RSpec选项。因此,请仅在阅读问题后回复。 最佳答案 我通过以下配置实现了您描述的行为:#torunonlyspecificspecs,add:focustothespec#describe"foo",:focusdo#OR#it"shouldfoo",:focusdoconfig.treat_symbols_as_metada

  6. ruby-on-rails - 将没有默认值的 NOT NULL 字段添加到填充的数据库中 - 2

    我有一个表,我们称它为MyTable。它是Postgresql数据库的一部分。MyTable中有很多条目,比方说超过一百万。我想向该表中添加一个字段,我们将其命名为MyNewField。它由ActiveRecord迁移添加。此字段没有默认值且不可为空。结果,在它的迁移类中将是这样的:classAddMyFieldToMyTable但是,它会触发一个错误(PG::NotNullViolation),因为该表已经包含行,所有这些行的MyField都设置为NULL。我想做的是:添加没有默认值且可空设置为false的行(不触发PG::NotNullViolation)。然后,将另一个表中的值插

  7. ruby-on-rails - rails : replacing try with the Null Object Pattern - 2

    在我的大多数应用程序中,我都有一个current_user方法。为了避免像current_user.name这样的情况出现异常,其中current_user是nil,rails提供了try方法。这个问题是我需要记住在current_user可能是nil的地方使用try。我想使用NullObject模式来消除这种额外的开销。classNullUserdefmethod_missing(method_name,*args)nilendenddefcurrent_userreturnNullUser.newunlessUserSession.find@current_user||=UserS

  8. ruby-on-rails - MySql 上的 Rails 复选框存储为 null 或零 - 2

    在我的Rails应用程序中,我有一个项目列表(如任务列表),每个项目都有几个复选框来设置参数。当我提交表单时,选中的框在数据库中存储为零,未选中的存储为空。问题是:有办法配置吗?将数据存储在更传统的0或1上,因为我认为将null存储为false并将0存储为true有点令人困惑,特别是如果另一个应用程序(如C应用程序)需要读取数据。 最佳答案 假设您正在使用的属性是club_member,如“您是club_member吗?”。请注意,在Ruby/Rails中,它现在的工作方式是,ifmodel.club_member如果未选中(值为n

  9. sql - 在多少种语言中,Null 不等于任何东西,甚至不等于 Null? - 2

    在多少种语言中,Null不等于Null? 最佳答案 在SQL(作为一种逻辑语言)中就是这样,因为null表示未知/未定义。但是,在编程语言(例如C++或C#)中,空指针/引用是具有特定含义的特定值——没有任何意义。两个无是等价的,但两个未知数不是等价的。造成混淆的原因是两个概念使用了相同的名称(null)。 关于sql-在多少种语言中,Null不等于任何东西,甚至不等于Null?,我们在StackOverflow上找到一个类似的问题: https://stac

  10. ruby-on-rails - JSON::ParserError: 757: '{ 处的意外标记 - 2

    当前哈希是{\"report_name\"=>\"Study/Control:ABIRATERONEACETATE-20151413355\",\"left_mue_start_date\"=>\"02-26-2015\",\"left_mue_end_date\"=>\"03-19-2015\",\"right_mue_start_date\"=>\"02-26-2015\",\"right_mue_end_date\"=>\"03-19-2015\",\"report_formulary_id\"=>\",7581\",\"mue\"=>\"true\",\"mue_type\"=

随机推荐