2017-12-18 300 views
1

我試圖解析看起來像這樣的JSON響應。如何使用Retrofit 2解析動態JSON(+嵌套對象)

{ 
    "Cryptsy": { 
     "AMC": [ 
      "BTC" 
     ], 
     "CIRC": [ 
      "BTC" 
     ], 
     "SYNC": [ 
      "BTC" 
     ] 
    }, 
    "Bitstamp": { 
     "EUR": [ 
      "USD" 
     ], 
     "ETH": [ 
      "USD", 
      "EUR" 
     ], 
     "XRP": [ 
      "USD", 
      "EUR", 
      "BTC" 
     ] 
    }, 
    // ... 
    // More objects... 
    // ... 
} 

正如你所看到的,這個有動態鍵,每個值也是動態鍵的對象。我試圖解析此使用retrofit2和GsonConverter但它會導致異常

W/System.err: java.lang.IllegalStateException: Expected a string but was BEGIN_OBJECT at line 1 column 2 path $ 

我認爲這是因爲JSON是嵌套的所有對象沒有任何固定鍵。

這是我的代碼。

PairListResponse.java

// This is the GSON model class 

class PairListResponse { 

    private Map<String, Map<String, String[]>> exchangePairs; 

    PairListResponse() { 
    } 

    Map<String, Map<String, String[]>> getExchangePairs() { 
     return exchangePairs; 
    } 

    void setExchangePairs(Map<String, Map<String, String[]>> exchangePairs) { 
     this.exchangePairs = exchangePairs; 
    } 

    Map<String, String[]> getTradingPairs(String fromSymbol) { 
     return exchangePairs.get(fromSymbol); 
    } 
} 

PairListDeserializer.java

public class PairListDeserializer implements JsonDeserializer<PairListResponse> { 

    private static final String TAG = PairListDeserializer.class.getSimpleName(); 

    @Override 
    public PairListResponse deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 
     final JsonObject jsonObject = json.getAsJsonObject(); 
     final Map<String, Map<String, String[]>> exchangePairs = readPairMap(jsonObject); 
     PairListResponse result = new PairListResponse(); 
     result.setExchangePairs(exchangePairs); 
     return result; 
    } 

    @Nullable 
    private Map<String, Map<String, String[]>> readPairMap(@NonNull final JsonObject jsonObject) { 
     // Initializing Hashmap for the outer object 
     final Map<String, Map<String, String[]>> result = new HashMap<>(); 

     for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) { 
      String exchange = entry.getKey(); 
      String fromSymbol; 
      String[] toSymbols; 
      JsonObject fsymbolObj = entry.getValue().getAsJsonObject(); 

     // Initializing Hashmap for inner objects 
      final Map<String, String[]> pairsPerCoin = new HashMap<>(); 

      for (Map.Entry<String, JsonElement> inner_entry : fsymbolObj.entrySet()) { 
       fromSymbol = inner_entry.getKey(); 
       toSymbols = toStringArray(inner_entry.getValue().getAsJsonArray()); 
       pairsPerCoin.put(fromSymbol, toSymbols); 
      } 
      result.put(exchange, pairsPerCoin); 
     } 
     return result; 
    } 

    private static String[] toStringArray(JsonArray array) { 
     if (array == null) return null; 
     String[] arr = new String[array.size()]; 
     for (int i = 0; i < arr.length; i++) { 
      arr[i] = array.get(i).toString(); 
     } 
     return arr; 
    } 
} 

提前感謝!

回答

0

對不起,我犯了一個最愚蠢的錯誤! 在我的翻新API調用中,我忘了設置正確的模型類名稱。

public interface TradingPairAPICall { 
    @GET("exchanges") 
    Call<String> getAllPairList(); 
} 

事實上,它需要

Call<PairListResponse> getAllPairList(); 

我改變它,它成功合作。