2017-01-11 70 views
1

我有一個屬於我無權訪問的第三方庫的類。它看起來像:如何將Jackson ObjectMapper配置爲使用自定義值序列化某些Bean的某些字段(如果它們爲null)?

public class Product { 

    private String thumbnailUrl;  

    // many other properties, some of which are POJOs or collections 

    public String getThumbnailUrl() { 
     return thumbnailUrl; 
    } 

    public void setThumbnailUrl(String thumbnailUrl) { 
     this.thumbnailUrl = thumbnailUrl; 
    } 
} 

這只是我將要使用Jackson序列化爲字符串的一個類。還有不少其他人。

thumbnailUrl財產有時可以是null。如何配置ObjectMapper將該字段序列化爲http://www.example.com/unknown.png,如果是null

我認爲我不能使用mixins,因爲mixin將無法訪問原始對象,因此他們無法檢查該屬性的值是否爲null

回答

0

這應該做的伎倆:

private String thumbnailUrl = "http://my.default.url";

正如意見中提到的OP,類來自於第三方庫,因此修改它(網HRS歐洲this SO)或註釋(一'la this SO)不是一種選擇。在這種情況下,你還有兩個選擇:

  • 補丁的第三方LIB(顯然你可以訪問源;))

  • 哈克自己的方式圍繞它的自定義序列化(需要雖然是很好的測試,而這種快速的黑客不會在多線程環境中工作)

如:

@Override 
public void serialize(Product value, JsonGenerator jgen, SerializerProvider provider) 
    throws IOException, JsonProcessingException { 
    boolean revert = false; 
    if (value.thumbnailUrl == null) { 
     value.thumbnailUrl = "http://my.default.url"; 
     revert = true; 
    } 
    jgen.writeObject(value); 
    if (revert) { 
     value.thumbnailUrl = null; 
    } 
} 
+0

正如問題中提到的,這是第三方類,我無法訪問源代碼。我想把這個邏輯外化。 – Outkast

+0

然後恐怕你得爲這個類編寫你自己的序列化程序。這有很多方法,例如,http://www.baeldung.com/jackson-custom-serialization當然你不能註釋這個類,但是仍然可以配置你的ObjectMapper來使用你的自定義序列化器爲類(也在鏈接的方法) –

+0

我可以寫一個自定義序列化器,但我希望序列化的所有方面保持原樣,並且只能自定義此字段的序列化。如果我爲具有20個字段的POJO編寫自定義序列化程序併爲所有20個字段添加序列化邏輯,那將非常糟糕。 – Outkast

0

我結束了這個解決方案,但它並不是這麼簡單,我期待它是:

@Test 
public void shouldSerializeDefaultThumbnailUrlIfThumbnailUrlIsNull() throws Exception { 
    // Given 
    Product p = new Product(); 
    p.setPrimaryKey("123"); 

    PropertyFilter filter = new SimpleBeanPropertyFilter() { 
     @Override 
     public void serializeAsField(Object pojo, JsonGenerator jgen, SerializerProvider prov, PropertyWriter writer) throws Exception { 
      if (pojo.getClass().equals(Product.class) 
        && ((Product) pojo).getThumbnailUrl() == null 
        && writer.getName().equals("thumbnailUrl")) { 
       jgen.writeStringField(writer.getName(), "http://www.example.com/default.png"); 
      } else { 
       writer.serializeAsField(pojo, jgen, prov); 
      } 
     } 
    }; 

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

    this.mapper.setFilterProvider(filters); 
    String json = this.mapper.writeValueAsString(p); 

    assertThat(json, equalTo("{\"thumbnailUrl\":\"http://www.example.com/default.png\",\"id\":\"123\"}")); 
} 

忽略這一點。它不適用於我的情況,因爲我的課需要註釋,而我不能。

+0

如果我可以爲'Product'類實現一個'com.fasterxml.jackson.databind.JsonSerializer',它與默認序列化程序相同,但只有這個規則只適用於這個特定的字段,那會更好。 – Outkast

+0

這確實很好,但我還沒有找到一個很好的,簡單的方法來做到這一點。 –

相關問題