2012-09-16 69 views
3

我解析JSON和我有一種結構可以有三種形式之一的困難。在我的情況下,它可能是零維的,一維的或二維的。有沒有什麼方法可以檢查JSON以確定它是哪一個?或者也許消費它,然後研究它是什麼。JSON消費者的多態對象

結構看起來像這樣,可以嵌入到其他結構中。

"details":{ 
    "Product":"A zero-dimensional Product" 
}, 

"details":{ 
    "Product":"A one-dimensional Product", 
    "Dimensions": [ "Size" ], 
    "Labels": [ "XS", "S", "M", "L" ] 
}, 

"details":{ 
    "Product":"A two-dimensional Product", 
    "Dimensions": [ "Size", "Fit" ], 
    "Labels": [[ "XS", "S", "M", "L" ],[ "26", "28", "30", "32" ]] 
} 

我可能在尋找的是一個通用的類,傑克遜將永遠匹配。

喜歡的東西翻譯:

{ 
"SomeField": "SomeValue", 
... 
"details":{ 
    ... 
} 
} 

分爲:

class MyClass { 
    String SomeField; 
    ... 
    AClass details; 
} 

有一類AClass我可以定義可能是任何JSON結構或陣列的通用接收者?

+0

但是是不是該尺寸和標籤都只是可選?否則這是普通的解析? –

+0

試試這個鏈接:http://stackoverflow.com/questions/2487841/jquery-parse-json-multidimensional-array –

+0

我可能被誤解了。我編輯了這個問題來改進(我希望)。關鍵是該結構可以是三種不同風味中的任何一種。我認爲我需要預先嚐試JSON來確定它的味道,或者消費任何類型的結構,然後再查找。 – OldCurmudgeon

回答

2

由於Eric的評論指向我programmerbruce我設法破解它。這是我使用的代碼(簡化爲簡化)。

public static class Info { 
    @JsonProperty("Product") 
    public String product; 
    // Empty in the 0d version, One entry in the 1d version, two entries in the 2d version. 
    @JsonProperty("Dimensions") 
    public String[] dimensions; 

} 

public static class Info0d extends Info { 
} 

public static class Info1d extends Info { 
    @JsonProperty("Labels") 
    public String[] labels; 
} 

public static class Info2d extends Info { 
    @JsonProperty("Labels") 
    public String[][] labels; 
} 

public static class InfoDeserializer extends StdDeserializer<Info> { 
    public InfoDeserializer() { 
    super(Info.class); 
    } 

    @Override 
    public Info deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { 
    Class<? extends Info> variantInfoClass = null; 
    ObjectMapper mapper = (ObjectMapper) jp.getCodec(); 
    ObjectNode root = (ObjectNode) mapper.readTree(jp); 
    // Inspect the `diemnsions` field to decide what to expect. 
    JsonNode dimensions = root.get("Dimensions"); 
    if (dimensions == null) { 
     variantInfoClass = Info0d.class; 
    } else { 
     switch (dimensions.size()) { 
     case 1: 
      variantInfoClass = Info1d.class; 
      break; 

     case 2: 
      variantInfoClass = Info2d.class; 
      break; 
     } 
    } 
    if (variantInfoClass == null) { 
     return null; 
    } 
    return mapper.readValue(root, variantInfoClass); 
    } 
} 

而且在ObjectMapper安裝此:

// Register the special deserializer. 
InfoDeserializer deserializer = new InfoDeserializer(); 
SimpleModule module = new SimpleModule("PolymorphicInfoDeserializerModule", new Version(1, 0, 0, null)); 
module.addDeserializer(Info.class, deserializer); 
mapper.registerModule(module); 
factory = new JsonFactory(mapper); 
2

這是你想要的AClass結構嗎?

class Dimension { 
    String name; 
    List<String> possibleValues; 
} 

class Product { 
    String name; 
    List<Dimension> dimensions; 
} 

所有你需要做的是改變dimensions列表的長度佔了三種類型。

解析成爲檢查JSON中是否存在Dimensions屬性的一個微不足道的問題,如果是,請遍歷它並追加到dimensions列表。


另一個想法是重組JSON(如果可以的話),使得所有的情況都是一樣的形式:

"d0":{ 
    "Product":"A zero-dimensional Product", 
    "Dimensions": {} 
}, 

"d1":{ 
    "Product":"A one-dimensional Product", 
    "Dimensions": { 
     "Size": [ "XS", "S", "M", "L" ] 
    } 
}, 

"d2":{ 
    "Product":"A two-dimensional Product", 
    "Dimensions": { 
     "Size": [ "XS", "S", "M", "L" ], 
     "Fit": [ "26", "28", "30", "32" ] 
    } 
} 
+0

好主意,不幸的是我發現你不能用JSON命名數組。 '「大小」:[「XS」,「S」,「M」,「L」]'無效。我還沒有完成你的第一個解決方案。 – OldCurmudgeon

+0

嗯,你可以「命名」一個數組?它[驗證](http://jsonlint.com/)對我來說很好... – Eric

+0

不,不,重構JSON應該是最後的手段。我寧願在我的最後解決一個解決方案。 – OldCurmudgeon