2014-11-20 143 views
0

我想反序列化使用傑克遜現有的JSON文件,並想知道是否有可能執行下面的翻譯,而不訴諸一堆自定義反序列化。傑克遜陣列元素POJO

輸入JSON看起來是這樣的:

{ 
    "type": "foo", 
    "content": ["a", "b", {"some": "object", "goes": "here"}, 4] 
} 

第3個content元素不改變,總是字符串,字符串,SomeDataStructure,整型(可選)

而且我想反序列化到這樣的事情:

class Foo { 
    public static class FooContent { 
     String some; 
     String goes; 
    } 

    String aString; 
    String bString; 
    FooContent content; 
    Integer cInt;  
} 

現在我已經遇到BeanAsArrayDeserializer,這聽起來喜歡它可能是我想要的,但我似乎無法找到任何東西,甚至像一段示例代碼,讓我開始。

那麼,有什麼想法?

回答

0

您始終可以實現您的自定義解串器。請參見下面的源代碼:

import java.io.IOException; 

import com.fasterxml.jackson.core.JsonParser; 
import com.fasterxml.jackson.core.JsonProcessingException; 
import com.fasterxml.jackson.core.JsonToken; 
import com.fasterxml.jackson.databind.DeserializationContext; 
import com.fasterxml.jackson.databind.JsonDeserializer; 
import com.fasterxml.jackson.databind.ObjectMapper; 
import com.fasterxml.jackson.databind.SerializationFeature; 
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; 

; 

public class JacksonTest { 

    public static void main(String[] args) throws Exception { 
     String json = "{\"type\": \"foo\",\"content\": [\"a\", \"b\", {\"some\": \"object\", \"goes\": \"here\"}, 4]}"; 

     ObjectMapper mapper = new ObjectMapper(); 
     mapper.configure(SerializationFeature.INDENT_OUTPUT, true); 
     mapper.configure(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS, true); 

     Root pojo = mapper.readValue(json, Root.class); 
     System.out.println(pojo); 
    } 
} 

class Root { 
    public String type; 
    @JsonDeserialize(using = FooDeserializer.class) 
    public Foo content; 

    @Override 
    public String toString() { 
     return content.toString(); 
    } 
} 

class Foo { 
    public static class FooContent { 
     public String some; 
     public String goes; 

     @Override 
     public String toString() { 
      return "{" + some + ", " + goes + "}"; 
     } 
    } 

    String aString; 
    String bString; 
    FooContent content; 
    Integer cInt; 

    @Override 
    public String toString() { 
     return "Foo [aString=" + aString + ", bString=" + bString + ", content=" + content 
       + ", cInt=" + cInt + "]"; 
    } 
} 

class FooDeserializer extends JsonDeserializer<Foo> { 

    @Override 
    public Foo deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, 
      JsonProcessingException { 
     Foo f = new Foo(); 
     int index = 0; 
     while (jp.nextToken() != JsonToken.END_ARRAY) { 
      JsonToken token = jp.getCurrentToken(); 
      if (token.isStructStart()) { 
       f.content = jp.readValueAs(Foo.FooContent.class); 
       index++; 
      } else { 
       switch (index++) { 
       case 0: 
        f.aString = jp.getText(); 
        break; 
       case 1: 
        f.bString = jp.getText(); 
        break; 
       case 3: 
        f.cInt = Integer.parseInt(jp.getText()); 
        break; 
       } 
      } 
     } 
     return f; 
    } 
} 

以上應用程序打印:

Foo [aString=a, bString=b, content={object, here}, cInt=4] 
+0

Nice code snippet Michal。看起來它只適用於單深度數組。你碰巧知道一個跟蹤嵌套數組索引而不用某種類型的字典來跟蹤數組/對象深度的簡單方法嗎?一直在想這個問題一段時間,領導可能會有所幫助。 – Conor 2015-10-28 22:42:07

+0

以上代碼是僅適用於上述數據結構的自定義實現。如果我們想要編寫更通用的解決方案,我們必須編寫新的陣列解串器,並嘗試配置它併爲屬性添加索引。 (反序列化器必須知道會發生什麼)。您可以使用示例'JSON'和'POJO'結構在SO上創建新問題。 – 2015-10-29 17:48:03

0

該功能允許使用BeanAsArrayDeserializer(內部)是@JsonFormat。您可以在this博客文章中閱讀關於它的一些信息。

我也剛剛瞭解到它,但我認爲適用於您的案例的映射看起來如下所示。你需要一個包裝器來保存content字段,然後它將是Foo類型。

@JsonFormat(shape = Shape.ARRAY) 
@JsonPropertyOrder({ "aString", "bString, "content", "cInt }) 
class Foo { 
    public static class FooContent { 
     String some; 
     String goes; 
    } 

    @JsonFormat(shape = Shape.STRING) 
    String aString; 

    @JsonFormat(shape = Shape.STRING) 
    String bString; 

    FooContent content; 

    @JsonFormat(shape = Shape.NUMBER) 
    Integer cInt;  
}