java - 如何使用 Retrofit 2 解析动态 JSON(+嵌套对象)

标签 java android json gson retrofit

我正在尝试解析如下所示的 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;
    }
}

提前致谢!

最佳答案

对不起,我犯了一个最愚蠢的错误! 在我的改造 API 调用中,我忘记设置正确的模型类名称。

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

事实上,它需要

Call<PairListResponse> getAllPairList();

我修改了一下,成功了。

关于java - 如何使用 Retrofit 2 解析动态 JSON(+嵌套对象),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47869699/

相关文章:

java - 用于计算 mfcc vector 的库

android - 如何在android的父级可扩展列表中添加图像?

php - 在表中显示 AJAX 响应

Java Applet 无法清除屏幕上的文本

java - 如何匹配来自不同类的两个页面对象文本?

java - 如何正确使用concurrentskiplistmap?

javascript - 访问 $.ajax 语句内分配的 JSON 时出现问题

java - Gradle:从运行时依赖项中排除 jar

android - LocationSettings 对话框出现,即使 GPS 打开

c# - Travian 更改村庄名称给 'Invalid Token' 与 webrequests