Gson解析没有键

时间:2017-07-06 20:54:10

标签: android json gson retrofit2

有人可以解释我,我如何解析JSON

{
"5": {
    "NumPossibleAchievements": "2",
    "PossibleScore": "15",
    "NumAchieved": 0,
    "ScoreAchieved": 0,
    "NumAchievedHardcore": 0,
    "ScoreAchievedHardcore": 0
},
"1838": {
    "NumPossibleAchievements": "48",
    "PossibleScore": "400",
    "NumAchieved": "48",
    "ScoreAchieved": "400",
    "NumAchievedHardcore": "48",
    "ScoreAchievedHardcore": "400"
},
"7634": {
    "NumPossibleAchievements": 0,
    "PossibleScore": 0,
    "NumAchieved": 0,
    "ScoreAchieved": 0,
    "NumAchievedHardcore": 0,
    "ScoreAchievedHardcore": 0
}
}

现在我上课了,我想用于回应

public class UserProgress {

private Map<String, Progress> userProgress;

public Map<String, Progress> getUserProgress() {
    return userProgress;
}
}

此类表示此地图中的内部对象

public class Progress {

@SerializedName("NumPossibleAchievements")
private String numPossibleAchievements;
@SerializedName("PossibleScore")
private String possibleScore;
@SerializedName("NumAchieved")
private int numAchieved;
@SerializedName("ScoreAchieved")
private int scoreAchieved;
@SerializedName("NumAchievedHardcore")
private int numAchievedHardcore;
@SerializedName("ScoreAchievedHardcore")
private int scoreAchievedHardcore;

.....

自定义反序列化器应该将此类型的JSON解析为普通对象。这个解串器我添加到改装转换器。

public class UserProgressDeserializer implements JsonDeserializer<UserProgress> {

@Override
public UserProgress deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
    final JsonObject jsonObject = json.getAsJsonObject();
    final Map<String, Progress> parameters = readParametersMap(jsonObject);
    final UserProgress result = new UserProgress();

    if (parameters != null) result.setUserProgress(parameters);
    return result;
}

@Nullable
private Map<String, Progress> readParametersMap(@NonNull final JsonObject jsonObject) {
    final JsonElement paramsElement = jsonObject.getAsJsonObject();
    if (paramsElement == null) return null;

    final JsonObject parametersObject = paramsElement.getAsJsonObject();
    final Map<String, Progress> parameters = new HashMap<>();
    for (Map.Entry<String, JsonElement> entry : parametersObject.entrySet()) {
        String key = entry.getKey();
        Progress value = new Gson().fromJson(entry.getValue().getAsString(), Progress.class);
        parameters.put(key, value);
    }
    return parameters;
}
}

我的要求

@GET("API_GetUserProgress.php")
Flowable<UserProgress> getUserProgress(@Query("u") @NonNull String userName,
                                                     @Query("i") String gamesCSV);

请求工作,在原始体中我看到JSON,但对象包含空映射。我测试了断点,但它从未进入解串器。现在我的想法是创建自定义函数,它将从响应原始体解析JSON字符串,但这将是尖峰。

感谢您的帮助

1 个答案:

答案 0 :(得分:0)

<强> UPD: 似乎GSON接受开箱即用的对象的地图 并将这些对象强制转换为 LinkedTreeMap 。因此,我们所需要的只是更改请求返回类型。

Flowable<Map<String, Progress>> getUserProgress(@Query("u") @NonNull String userName,
                                                @Query("i") String gamesCSV);

<强>冗余

我没有使用自定义反序列化器,所以我实现了接受来自原始响应的JSON字符串的新函数,将结果映射到所需对象列表。现在它看起来像

Flowable<ResponseBody> flowable = USERS_API.getUserProgress(userName, gameIDsCSV);
    return manageRequestWithMapper(flowable, responseBody -> {
        String body = responseBody.string();
        JSONObject yourJSON = new JSONObject(body);
        Iterator<String> keysIterator = yourJSON.keys();
        List<Progress> tempList = new ArrayList<>();
        while (keysIterator.hasNext()) {
            String key = keysIterator.next();
            JSONObject actualObj = (JSONObject) yourJSON.get(key);
            tempList.add((new Gson()).fromJson(actualObj.toString(), Progress.class));
        }
        return tempList;
    });