2017-07-18 58 views
0

嵌套的列表和關鍵,我需要在Java中1.7與傑克遜反序列化這一點,使用貨幣作爲價值:反序列化JSON - 需要作爲價值

"prices": { 
    "USD": [ 
     [1, "1.99000"], 
     [100, "1.89000"], 
     [1000, "1.40500"] 
    ], 
    "EUR": [ 
     [1, "1.53000"], 
     [100, "1.45000"], 
     [1000, "1.08350"] 
    ] 
} 

(來源就是這個REST API https://octopart.com/api/docs/v3/rest-api#notes-partoffer.prices

我的目標是爲每個價格獲得具有屬性貨幣,價格中斷和價格的對象。

我無法弄清楚如何執行該操作。我試過如下:

  1. 反序列化整個「價格」作爲字符串進行進一步的處理(沒有工作,得到了無法反序列化java.lang.String中的實例進行START_OBJECT令牌 - 很明顯,因爲這是JSON_OBJECT)

  2. 反序列化就像

    LinkedHashMap<String, LinkedHashMap<Integer, String>>> 
    

(本Deserializing Jackson by using a key as value啓發,但也沒有工作)

  • 使用這樣的包裝:

    public class PartOfferPriceWrapper { 
    
    private LinkedHashMap<String, List<Entry<Integer, String>>> prices; 
    
    } 
    
  • 然後處理等:

    List<PartOfferPrice> partOfferPriceList = new ArrayList<PartOfferPrice>(); 
    
        for (Entry<String, List<Entry<Integer, String>>> currencyEntry : 
        partOfferPrices.entrySet()) { 
    
         for (Entry<Integer, String> priceEntry : currencyEntry.getValue()) { 
         PartOfferPrice partOfferPrice = new PartOfferPrice(); 
    
         partOfferPrice.setOffer_id(partOfferId); 
         partOfferPrice.setCurrency(currencyEntry.getKey()); 
         partOfferPrice.setPriceBreak(priceEntry.getKey());    
    
         partOfferPrice.setPrice(Double.parseDouble(priceEntry.getValue())); 
    
         partOfferPriceList.add(partOfferPrice); 
         } 
    

    這似乎很好,但結果是空(這是更大反應的一部分,閱讀Response.readEntity是成功的)。我找不到任何其他方式來處理這個(一些自定義的解串器?)。

    編輯

    我試圖使用自定義解串器下面提馬的建議是:

    public class PartOfferPricesWrapperDeserializer extends 
        JsonDeserializer<PartOfferPricesWrapper> { 
    
        public PartOfferPricesWrapperDeserializer() { super(); } 
    
        @Override 
        public PartOfferPricesWrapper deserialize(JsonParser jsonParser, 
         DeserializationContext context) throws IOException, 
         JsonProcessingException { 
    
         PartOfferPricesWrapper partOfferPricesWrapper = new 
         PartOfferPricesWrapper(); 
         List<PartOfferPrice> priceList = new ArrayList<PartOfferPrice>(); 
    
         JsonNode node = jsonParser.readValueAsTree(); 
    
         Iterator<Entry<String, JsonNode>> nodes = 
         node.get("prices").fields(); 
    
         while (nodes.hasNext()) {    
          Map.Entry<String, JsonNode> entry = nodes.next();    
          for (JsonNode tempNode : entry.getValue()) { 
    
           PartOfferPrice price = new PartOfferPrice(); 
           price.setCurrency(entry.getKey()); 
    
           for (int i = 0; i < tempNode.size(); i++) { 
    
            if (tempNode.get(i).isInt()) { 
             price.setPriceBreak(tempNode.get(i).intValue());        
            } 
            else 
            { 
             price.setPrice(tempNode.get(i).asDouble());       
            }           
           } 
    
          priceList.add(price); 
          } 
         } 
         partOfferPricesWrapper.setPrices(priceList); 
         return partOfferPricesWrapper; 
        } 
    } 
    

    添加此到處理方法:

    SimpleModule module = new SimpleModule(); 
        module.addDeserializer(PartOfferPricesWrapper.class, new 
        PartOfferPricesWrapperDeserializer()); 
        objectMapper.registerModule(module);   
    
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, 
        false); 
        partsMatchResponse = objectMapper.readValue(target.getUri().toURL(), 
        PartsMatchResponse.class); 
    

    如果響應包含可能會工作只有「價格」節點,但現在我得到Node.get(「價格」)NullPointerException。它可能試圖解析整個響應,但我只需要將「自定義解串器」用於「價格」部分。它有可能嗎?

    非常感謝。

    回答

    0

    是的,一個自定義的解串器可以工作。

    class CustomDeserializer extends JsonDeserializer<Prices> { 
    
        public CustomDeserializer() { super(); } 
    
        @Override 
        public Prices deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException, JsonProcessingException { 
         JsonNode node = jsonParser.readValueAsTree(); 
    
         Iterator<Entry<String, JsonNode>> nodes = node.get("prices").fields(); 
    
         while (nodes.hasNext()) { 
          Map.Entry<String, JsonNode> entry = nodes.next(); 
    
          System.out.println(entry.getKey()); 
    
          for (JsonNode tempNode : entry.getValue()) { 
           for (int i = 0; i < tempNode.size(); i++) { 
            System.out.println(tempNode.get(i).getClass() + "\t" + tempNode.get(i)); 
           } 
          } 
    
          System.out.println(); 
         } 
    
         return null; 
        } 
    } 
    

    輸出

    USD 
    class com.fasterxml.jackson.databind.node.IntNode 1 
    class com.fasterxml.jackson.databind.node.TextNode "1.99000" 
    class com.fasterxml.jackson.databind.node.IntNode 100 
    class com.fasterxml.jackson.databind.node.TextNode "1.89000" 
    class com.fasterxml.jackson.databind.node.IntNode 1000 
    class com.fasterxml.jackson.databind.node.TextNode "1.40500" 
    
    EUR 
    class com.fasterxml.jackson.databind.node.IntNode 1 
    class com.fasterxml.jackson.databind.node.TextNode "1.53000" 
    class com.fasterxml.jackson.databind.node.IntNode 100 
    class com.fasterxml.jackson.databind.node.TextNode "1.45000" 
    class com.fasterxml.jackson.databind.node.IntNode 1000 
    class com.fasterxml.jackson.databind.node.TextNode "1.08350" 
    

    您可以創建你在想解串器(Prices是我用了一個空類)對象和結構。

    編輯

    您可以使用相同的自定義解串器只是爲現場的小變化。

    前兩行成爲下面所示的一樣,因爲你並不需要去尋找prices節點,因爲當它反序列化領域也只會通過JSON該字段。其餘的行是相同的。

    JsonNode node = jsonParser.readValueAsTree(); 
    Iterator<Entry<String, JsonNode>> nodes = node.fields(); 
    

    然後在您的包裝類:

    class PricesWrapper { 
    
        // ... 
    
        @JsonDeserialize(using = CustomDeserializer.class) 
        private Prices prices; 
    
        // ... 
    } 
    
    +0

    好,謝謝,我會嘗試。但是由於Price只是響應的一小部分(與PriceOffer有關,它與Part有關,但都是一大塊數據),似乎我必須自定義反序列化整個響應? – budul

    +0

    @budul不用客氣。我已經編輯了字段反序列化的問題。 – tima

    +1

    Tima,它的工作原理!我非常感謝你的幫助,因爲我花了將近兩天的時間來解決這個問題,今天我應該提出一些結果......只有一件事讓我感到惱火 - 我無法自己解決它:-)(甚至不得不註冊到SO ...)。非常感謝。 – budul