java8 - 缺少变量和可选

Dav*_*ezo 7 java json jackson java-8

我正在解析输入JSON.对于一个领域,有三种可能性:

  • 这个领域缺席;
  • 该值设置为null;
  • 该值设置为有效的值.

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

Optional想要模仿这个:

public class Data {
    private Optional<String> field;
}
Run Code Online (Sandbox Code Playgroud)

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

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

FWIW,我使用Jackson和模块jackson-datatype-jdk8来解析输入JSON.

Fed*_*ner 5

我认为你不应该使用Optional这种情况.正如@dkatzel在他的回答中所提到的,它意味着比作为字段更多地用作API返回值.

尽管进行了这种学术讨论,但只需将Data类中的字段初始化为默认值即可完成您想要的任务:

public class Data {
    private String field = DEFAULT_VALUE;
}
Run Code Online (Sandbox Code Playgroud)

然后让杰克逊做其余的事情.


根据OP的评论编辑:

当你的JSON附带一个null值时field,Jackson会将其设置为null,这就是将存储在数据库中的内容.

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

当你的JSON确实包含一个值时field,Jackson会设置它,并且该值将到达数据库.


编辑2,考虑OP的要求,在解析JSON输入后,找出输入JSON field中是否填充,设置null或缺席:

如果在解析输入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);
    }
}
Run Code Online (Sandbox Code Playgroud)

在这里,我使用了一个private static属性来保存你Data的默认值和3个方法来查询任何字段状态(默认值,null或set).为了确定要查询的字段,这些方法接收a Function<Data, Object>,给定一个Data实例并返回一个Object应该是所需字段的字段.(如果你停下来思考它,可以将getter视为将实例作为输入并返回实例的特定字段的函数).

所以稍后,当你需要知道某个字段如何到达你的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
Run Code Online (Sandbox Code Playgroud)