2017-12-18 289 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(); 

我改变它,它成功合作。