[英]java8 - absent variable & Optional
我正在解析輸入JSON。 對於一個領域,有三種可能性:
實現了不同的行為:對於JSON中缺少的值,將默認值插入到數據庫中; 對於JSON中的空值,將空值插入到數據庫中。
我想到了Optional
模型:
public class Data {
private Optional<String> field;
}
以下哪兩個選項最有意義?
field
為null,則JSON中不存在該字段。 如果field
為Optional.empty,則JSON中的字段為null
。 field
為null,則JSON中的字段為null
。 如果field
為Optional.empty,則JSON中不存在該字段。 FWIW,我使用Jackson和模塊jackson-datatype-jdk8來解析輸入JSON。
我認為你不應該在這種情況下使用Optional
。 正如@dkatzel在他的回答中所提到的,它意味着比作為字段更多地用作API返回值。
盡管進行了這方面的學術討論,但只需將Data
類中的字段初始化為默認值即可實現您的目標:
public class Data {
private String field = DEFAULT_VALUE;
}
然后讓傑克遜做其余的事情。
根據OP的評論編輯:
當您的JSON為field
提供null
值時,Jackson會將其設置為null
,這將存儲在數據庫中。
當您的JSON不包含該字段時, DEFAULT_VALUE
將自動加載到您的Data
實例中。
當你的JSON確實包含該field
的值時,Jackson將設置它,並且該值將到達數據庫。
編輯2,考慮到OP要求在解析JSON輸入后找出field
是填入,設置為null
還是在輸入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個方法來查詢任何字段狀態(默認值,null或set)。 為了確定要查詢的字段,這些方法接收一個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
我會說第一個選項具有最大的語義意義。 它還可能允許更容易的計算。
如果java中的字段為null,則表示缺少與第一個選項匹配的值。
我建議您將這些字段存儲在哈希映射中,其中鍵是JSON字段名稱,值是JSON字段的值。 我還建議你不要在這里使用一個可選項(因為它可以添加一個不必要的復雜層),而是在hashmap中使用null或非null對象。
HashMap<String, Value> jsonFields = new HashMap<String, Value>();
boolean hasField1 = false;
Value field1Value = null;
if(jsonFields.contains("field1"){ // It is present in the JSON file
field1Value = jsonFields.get("field1"); // "null" here would mean that the JSON field was set to "null"
hasField1 = true;
}
第二種選擇對我來說更有意義。 null
表示null
,empty表示不存在。
但是, Optional
不應該真正用作字段。 它應該被用作API返回值 。
您可以將數據存儲在允許空值的Map
中嗎? 如果地圖中沒有關鍵字(您的字段),則返回Optional.empty
?
都不是? 我會用@DefaultValue()注釋我的POJO字段。 然后,您的可能性是在JSON中指定的空值或非空值,或者如果從JSON中省略該字段,則為默認值。 然后,您可以在沒有任何特殊的每場分析的情況下堅持POJO。
如果您正在處理Object
而不是String
,那么這是一個我覺得優雅的解決方案:
Optional.empty();
如果沒有價值 Optional.of(value)
使用Optional.of(value)
Optional.of(specialValue)
其中specialValue
是一個靜態單例,你可以輕松測試,例如: ObjectUtils.NULL
(來自commons.lang )。
然后你可以輕松測試你的可選:
if (optional.isPresent()) {
if (ObjectUtils.NULL.equals(optional.get())) {
// value is there and null
} else {
// value is there and not null
}
} else {
// value is not there
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.