2014-02-14 32 views
2

我想反序列化兩種類型的JSON:提供了傑克遜映射多種方式來反序列化同一對象

{ 
    name: "bob", 
    worksAt: { 
     name: "Bobs department store", 
     location: "downtown" 
    }, 
    age: 46 
} 

{ 
    name: "Tom", 
    worksAt: "company:Bobs department store", 
    age: 27 
} 

到這些對象:

UML of classes

第一種方式創建兩個新對象,第二種方式請求對象從t他數據庫基於一個字符串的內容。

有點像傑克遜映射器如何反序列化將任意字符串的對象,這樣的對象:

public class Company{ 
    public String name; 
    public Employee[] employees 
    public Company(){} 
    public Company(String json){ 
     //turn string into object using whatever encoding you want blah blah blah... 
    } 
} 

麻煩的是我需要兩者。我需要它來處理對象和字符串。兩者都可以從相同的輸入中得到。

我嘗試的第一個想到的就是製作轉換

它說,這些創建一個委託類型傳遞給解串器,但轉換器始終應用於即使數據類型不是字符串。所以這沒有奏效。

我也試過一個正常的反序列化器,但是我找不到推遲到BeanDeserializer的方法。 beanDeserializer非常複雜,我無法手動實例化它。我也看不到在傑克遜映射器中默認的反序列化器。

我是否必須重新實現傑克遜映射器反序列化才能做到這一點?反序列化器是否有任何方式說「我不能這樣做,使用默認實現」?

編輯:一些進一步的進展。基於傑克遜映射器的源代碼,它看起來像你可以instatiate豆解串器是這樣的:

DeserializationConfig config = ctxt.getConfig(); 
JavaType type = config.constructType(_valueClass); 
BeanDescription introspect = config.introspect(type); 
JsonDeserializer<Object> beanDeserializer = ctxt.getFactory().createBeanDeserializer(ctxt, type , introspect); 

,但由於某種原因,所有的_beanProperties有FailingDeserializer組爲他們_valueDeserializer整個事情失敗。所以,我不知道爲什麼出現這種情況?

回答

2

你試過writing a custom deserializer?這使您能夠最有效地控制傑克遜如何反序列化對象。您可以嘗試以單向方式反序列化,如果出現錯誤,請嘗試其他方法。

傑克遜也可以處理polymorphic deserialization,儘管這需要對json進行一些小的更改以包含類型信息,而且聽起來好像您的問題約束可能不允許這樣做。

+0

是的。事實上,我確實試圖實現一個自定義的解串器。但是我撞到了一堵牆。它將允許我從一個字符串反序列化一個對象,但是如果傳入一個json對象會發生什麼?手動反序列化系統中的許多嵌套對象是不行的。我需要使用bean解串器來完成它。但是,一旦我爲一個對象定義了反序列化器,我就無法再訪問bean解串器了! – Ghoughpteighbteau

1

如果我理解正確的問題,我會建議使用JsonNode。您可以定義您的頂級型二傳手是這樣的:

setWorksAt(JsonNode node) { 
    if (node.getNodeType == JsonNodeType.STRING) { 
     String name = node.getText(); 
     name = name.substring(name.lastIndexOf(':')); 
     this.company = new Company(name); 
    } else if (node.getNodeType == JsonNodeType.OBJECT) { 
     this.company = mapper.treeToValue(node, Company.class); 
    } 
} 

這讓你來處理兩個獨立的worksFor輸入,同時還允許標準的映射以處理任何子爲對象的情況。

+0

我不知道我可以在setter中獲得JsonNode!但是,如何獲得映射器?我創建的對象是POJO,比結構稍多一些,並且無法訪問映射器。我不喜歡使用singelton來獲得它的想法。另外,還有一個缺點是它會被重定向到對象的setter中,這也會阻止我在沒有自動添加更多內容的情況下混淆數據庫。我不得不違反我的項目中的一些標準來擺脫這個問題。公平起見。我不認爲我在這個問題中提到了這些限制... – Ghoughpteighbteau

+0

是的,我正在使用單例來獲取我的實現中的映射器。我認爲你也可以使用依賴注入,但我沒有用過,所以我不知道具體情況。如果你可以解釋你的數據庫限制,我可以試着去考慮是否有一種方法可以使用Jackson來適應這兩種情況。 –

0

隨着傑克遜的最新版本(2.8+我認爲,與2肯定能行。9)你可以使用多個@JsonCreator並做這樣的事情:

public class Company { 
    private String name; 
    private String location; 

    private Company(String name, String location) { 
     this.name = name; 
     this.location = location; 
    } 
    private Company(String stringRepresentation) { 
     // add code here to parse string and extract name and location 
    } 

    @JsonCreator 
    private static Company fromJson(
      @JsonProperty("name") String name, 
      @JsonProperty("location") String location) 
    { 
     return new Company(name, location); 
    } 

    @JsonCreator 
    private static Company fromJson(String str) { 
     return Company(str); 
    } 
}