2012-08-23 203 views
6

使用傑克遜2,我正在尋找一個通用方式將對象序列化爲單個值(然後序列化它們回來後填充只有單個字段),而不必重複創建一個JsonSerializer/JsonDeserializer來處理每個案例。 @JsonIdentityInfo註釋非常接近,但稍微遺漏了標記,因爲據我所知,它總是會首次序列化整個子對象。傑克遜 - 序列化/反序列化屬性作爲JSON值

這是我想要做的一個例子。鑑於類:

class Customer { 

    Long id = 99; 
    String name = "Joe"; 
    // Lots more properties 
} 

class Order { 
    String orderNum = "11111" 
    @WhateverAnnotationsINeedHereToDoWhatIWant 
    Customer customer; 
} 

我想爲了序列,作爲(或者是完全可以接受的我):

{"orderNum":"11111", "customer":"99"} 
{"orderNum":"11111", "customer":{"id":99}} 

@JsonIdentityInfo做些什麼使得它處理客戶端上更加困難(我們可以假設客戶知道如何將客戶ID映射回完整的客戶信息)。

@JsonIgnoreProperties也可能會顯示第二個JSON非常接近,但意味着我將不得不選擇退出所有內容但我想要的。

當我反序列化回來時,我只希望客戶只用「id」字段進行初始化。

任何奇怪的方式來做到這一點,我失蹤了,而沒有進入傑克遜soupy內部?據我所知,JsonDeserializer/JsonSerializer沒有關於父母的上下文信息,所以似乎沒有一種簡單的方法來創建一個@JsonValueFromProperty(「id」)類型的Jackson Mix-in,然後只需查看該註釋自定義串行器/解串器。

任何想法將不勝感激。謝謝!

回答

8

我曾經需要對不同類型的請求返回的JSON進行精細控制,恐怕我最終會使用自定義序列化器和反序列化器。

一個簡單的替代方法是增加@JsonIgnore到訂單的客戶領域,並添加以下吸氣訂購:

@JsonProperty("customer") 
public Long getCustomerId(){ 
    if (customer != null){ 
    return customer.getId(); 
    } 
    else { 
    return null; 
    } 
} 

返回然後JSON是:

{"orderNum":"11111", "customer":"99"} 
+0

感謝集成東西!這個簡單的解決方案實際上對我來說似乎非常可行,而且現在看起來非常明顯;)。在沒有@JsonIgnorePropertiesExcept(「id」)註釋的情況下,我認爲這樣做會很好。 – jonc

4

的另一種可能使用@JsonValue,用於id字段。

Jackson 2.1將添加一個功能強制甚至強制引用的序列化爲id(由新屬性「firstAsId」爲@JsonIdentityInfo)。對於所有情況,這可能不適用於反序列化,但可能適用於您。

+0

感謝StaxMan。不幸的是,@JsonValue並不能真正解決這個問題,因爲如果我只是自己序列化客戶,那麼我會期望記錄被完全序列化。 – jonc

+1

好的。那麼你最好的選擇是傑克遜2.1 - 它將允許從類型的序列化中分離引用(總是使用id)。 – StaxMan

+4

最後爲了試用2.1版本,因爲它在10月份發佈了:)。@JsonIdentityReference(alwaysAsId = true)和@JsonIdentityInfo(generator =「generator = ObjectIdGenerators.PropertyGenerator.class」)在序列化結束時效果很好,但在反序列化時不太好,因爲它無法解析對象ID引用。它可以與JPA提供者一起實例化一個空對象並僅設置ID進行反序列化,但不確定如何強制jackson解串器執行此操作,而無需爲每種可能的引用類型定義自定義解串器 – jonc