2017-09-13 87 views
3

我試圖在POJO中使用Optional來指示何時json字段可以爲空,不存在或存在。我的問題是,我不知道如何配置傑克遜不會像Optional.empty()null一樣。對於empty(),我希望該字段被忽略。 JsonInclude值沒有一個可以做到這一點。 Jdk8Module#configureAbsentsAsNulls()看起來很有前途,但它不會改變我的測試結果。有沒有辦法做到這一點?Jackson可選字段爲空()vs null

TL;博士 null被序列化,Optional.empty()不應被序列化。

以下是一些展示我試圖實現的行爲的測試。

class POJO { 
    public Optional<String> content; 
} 

private ObjectMapper getMapper() { 
    return new ObjectMapper().registerModule(new Jdk8Module()); 
} 

@org.junit.Test 
public void testAbsent() throws JsonProcessingException { 
    ObjectMapper mapper = getMapper(); 

    POJO pojo = new POJO(); 
    pojo.content = Optional.empty(); 

    String result = mapper.writeValueAsString(pojo); 

    assertEquals("{}", result); 
} 

@org.junit.Test 
public void testNull() throws JsonProcessingException { 
    ObjectMapper mapper = getMapper(); 

    POJO pojo = new POJO(); 
    pojo.content = null; 

    String result = mapper.writeValueAsString(pojo); 

    assertEquals("{\"content\":null}", result); 
} 

@org.junit.Test 
public void testPresent() throws JsonProcessingException { 
    ObjectMapper mapper = getMapper(); 

    POJO pojo = new POJO(); 
    pojo.content = Optional.of("Hello"); 

    String result = mapper.writeValueAsString(pojo); 

    assertEquals("{\"content\":\"Hello\"}", result); 
} 
+0

請你張貼小例子你期望通過但失敗的測試用例(例如,配置映射器,將字段設置爲空,序列化,顯示輸出)? – chrylis

+0

只是增加了一些測試。對不起,他們不在那裏開始。 – Panda

+0

正如我在原始問題(並在測試中指出的)中所說的,null應該被序列化並且empty()不應該。這不是模塊的默認行爲。這個問題並沒有回答如何實現這種行爲。 – Panda

回答

0

如果您檢查@JsonInclude註釋here,這是用來指定哪些字段應該被忽略或者基於字段的值序列化的傑克遜文檔,你可以看到,有一對夫婦的參數(NON_ABSENTNON_EMPTY ),可用於忽略Optional.empty值,但它們與null值組合在一起,因此它們不適用於您的情況。

你可以做的是創建一個JsonFilter來檢查字段的值,並忽略它們,如果它們是Optional.empty

PropertyFilter optionalFilter = new SimpleBeanPropertyFilter() { 

    @Override 
    public void serializeAsField(Object pojo, JsonGenerator jgen, SerializerProvider provider, PropertyWriter writer) throws Exception { 
     // get the field using the writer's name (field name) 
     Field field = pojo.getClass().getDeclaredField(writer.getFullName().toString()); 

     // get the value of the field, by making it accessible and then reverting 
     boolean defaultAccess = field.isAccessible(); 
     field.setAccessible(true); 
     Object value = field.get(pojo); 
     field.setAccessible(defaultAccess); 

     // serialize if null or it is not Optional.empty 
     if (value == null || value.equals(Optional.empty()) == false) { 
      writer.serializeAsField(pojo, jgen, provider); 
     } 
    } 
}; 

這將檢查類的每個字段和序列化,如果是null或大於Optional.empty的任何其他。

在主類中使用它:

FilterProvider filters = new SimpleFilterProvider().addFilter("optionalFilter", optionalFilter); 

// note that you need the `Jdk8Module` module to get the value of the optional 
ObjectMapper mapper = new ObjectMapper().registerModule(new Jdk8Module()); 

POJO pojo = new POJO(); 
pojo.setContent(Optional.empty()); 

System.out.println(mapper.writer(filters).writeValueAsString(pojo)); 

pojo = new POJO(); 
pojo.setContent(null); 

System.out.println(mapper.writer(filters).writeValueAsString(pojo)); 

pojo = new POJO(); 
pojo.setContent(Optional.of("Hello")); 

System.out.println(mapper.writer(filters).writeValueAsString(pojo)); 

還與過濾器註釋類:

@JsonFilter("optionalFilter") 
class POJO { 

} 

輸出:

{} 
{"content":null} 
{"content":"Hello"} 
相關問題