/ / Gson analyser un objet cartographique sans clé - android, json, gson, retrofit2

Gson analyse l'objet de la carte sans clé - Android, json, gson, retrofit2

quelqu'un peut-il m'expliquer, comment analyser 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
}
}

Maintenant, je "classe que je veux utiliser pour la réponse

public class UserProgress {

private Map<String, Progress> userProgress;

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

Aussi la classe qui représente l'objet intérieur dans cette carte

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;

.....

Et désérialiseur personnalisé qui doit analyser ce type JSON à objet normal. Ce désérialiseur, j’ai ajouté au convertisseur de conversion.

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;
}
}

Et ma demande

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

Demande de travail, dans le corps brut, je vois que JSON, maisobjet contient une carte vide. J'ai testé avec des points d'arrêt, mais cela n'entre jamais dans le désérialiseur. Maintenant, mon idée est de créer une fonction personnalisée qui analysera la chaîne JSON du corps brut de la réponse, mais ce sera un pic.

Merci pour toute aide

Réponses:

0 pour la réponse № 1

UPD: On dirait que GSON accepte Carte pour objets hors de la boîte et jeter ces objets à LinkedTreeMap. Donc, tout ce dont nous avions besoin était de changer le type de retour de demande.

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

REDONDANT

Je n’ai eu aucun succès avec le désérialiseur personnalisé, j’ai donc implémenté une nouvelle fonction qui accepte la chaîne JSON de réponse brute, mappe le résultat à la liste des objets requis. Et maintenant ça ressemble à

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;
});