java8 - 缺少变量和可选

标签 java json jackson java-8

我正在解析输入的 JSON。对于一个字段,有 3 种可能性:

  • 该字段不存在;
  • 该值设置为空;
  • 该值设置为有效值。

实现了不同的行为:对于 JSON 中不存在的值,将默认值插入到数据库中;对于 JSON 中的空值,将空值插入到数据库中。

我考虑过可选来对此建模:

public class Data {
    private Optional<String> field;
}

以下两个选项中哪个最有意义?

  1. 如果 field 为 null,则该字段在 JSON 中不存在。如果 field 为 Optional.empty,则该字段在 JSON 中为 null
  2. 如果 field 为 null,则该字段在 JSON 中为 null。如果 field 为 Optional.empty,则该字段在 JSON 中不存在。

FWIW,我使用带有模块 jackson-datatype-jdk8 的 Jackson 来解析输入的 JSON。

最佳答案

我认为你不应该使用 Optional对于这种情况。正如@dkatzel 在他的回答中提到的,它更应该用作 API 返回值而不是字段。

尽管进行了这种学术讨论,但您可以通过初始化 Data 中的字段来简单地完成您想要的。类的默认值:

public class Data {
    private String field = DEFAULT_VALUE;
}

然后让 Jackson 完成剩下的工作。


根据 OP 的评论进行编辑:

当您的 JSON 带有 nullfield 的值, Jackson 会将其设置为 null ,这就是将存储在数据库中的内容。

当您的 JSON 不包含该字段时,DEFAULT_VALUE将自动加载到您的 Data 中实例。

当您的 JSON 实际上包含 field 的值时, Jackson 将设置它,该值将到达数据库。


编辑 2,考虑到 OP 要求查明 field 是否存在要么被填写,设置为null或者在解析 JSON 输入后在输入 JSON 中不存在:

如果,在解析输入的 JSON 之后,您需要知道 field 是否是要么被填写,设置为null或不存在,然后考虑这个例子,它展示了我将采取的方法:

public class Data {

    private String field1 = "hello";

    private Integer field2 = 10;

    private Double field3 = 3.75;

    private static final Data DEFAULTS = new Data(); // defaults will be kept here

    public String getField1() {
        return this.field1;
    }

    public void setField1(String field1) {
        this.field1 = field1;
    }

    public Integer getField2() {
        return this.field2;
    }

    public void setField2(Integer field2) {
        this.field2 = field2;
    }

    public Double getField3() {
        return this.field3;
    }

    public void setField3(Double field3) {
        this.field3 = field3;
    }

    @Override
    public String toString() {
        return "Data [field1=" + this.field1 + 
                   ", field2=" + this.field2 + 
                   ", field3=" + this.field3 + "]";
    }

    public boolean isDefault(Function<Data, Object> getter) {
        Object defaultProperty = getter.apply(DEFAULTS);
        Object actualProperty = getter.apply(this);
        return defaultProperty != null // needed to support fields with no default value
            && defaultProperty.equals(actualProperty);
    }

    public boolean isNull(Function<Data, Object> getter) {
        return getter.apply(this) == null;
    }

    public boolean isSet(Function<Data, Object> getter) {
        return !this.isNull(getter) && !this.isDefault(getter);
    }
}

这里我使用了 private static属性来保存你的 Data的默认值和 3 种方法来查询任何字段状态(默认、空或设置)。为了确定要查询的字段,这些方法会收到一个 Function<Data, Object>。 , 给定一个 Data实例并返回 Object那应该是所需的字段。 (如果你停止思考,getters 可以看作是将实例作为输入并返回实例的特定字段的函数)。

所以稍后,当您需要知道某个字段如何到达您的 JSON 输入时,只需使用这 3 种查询方法来找出:

ObjectMapper m = new ObjectMapper();

String json = "{\"field1\":null,\"field2\":20}";
Data data = m.readValue(json, Data.class);

System.out.println(data); // Data [field1=null, field2=20, field3=3.75]

System.out.println("field1 default ? " + data.isDefault(Data::getField1)); // false
System.out.println("field1 null ? " + data.isNull(Data::getField1)); // true
System.out.println("field1 set ? " + data.isSet(Data::getField1)); // false

System.out.println("field2 default ? " + data.isDefault(Data::getField2)); // false
System.out.println("field2 null ? " + data.isNull(Data::getField2)); // false
System.out.println("field2 set ? " + data.isSet(Data::getField2)); // true

System.out.println("field3 default ? " + data.isDefault(Data::getField3)); // true
System.out.println("field3 null ? " + data.isNull(Data::getField3)); // false
System.out.println("field3 set ? " + data.isSet(Data::getField3)); // false

关于java8 - 缺少变量和可选,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31456327/

相关文章:

java - 井字游戏 'X' 直到第二个 'O' 被点击后才出现

java - GridBagLayout 困难

javascript - 使用在 AJAX 中获得的 JSON 数据填充 JSTree

ios - 从 NSDictionary 获取 JSON 子元素

c# - 从 VAT eu 解析一个 json

java - 线程 "main"中的异常 org.openqa.selenium.WebDriverException : Timed out waiting 45 seconds for Firefox to start after geckodriver upgradation

json - 如何在WildFly中将JSON java.util.Date变量序列化为ISO-8601格式的日期字符串?

java - Jackson XML 映射器强制使用小写 XML 标签

java - 使用列表值映射解析 Yaml 时出现 Jackson 异常

java - Android 上的装箱和拆箱