Using the Gson library to dynamically analyze unknown data
I want to parse the following JSON data in Android Studio using the Gson library. But the data is generalized. I don't know what keys (objects) get into the data.
under the school object - there is number 1103, which is the object.
and under this object we have shoolname, shortname, students again under students - there are IDs 2201, 2202 ... these objects are dynamic, I don't know what comes back.
So the question is how to parse this json string in android using Gson?
or any other solution for this is welcome
{
"schools": {
"home": "1103",
"statelevel": "1348"
},
"school": {
"1103": {
"schoolname": "Indira School",
"nameshort": "ind",
"students": {
"2201": {
"name": "Ritesh",
"isCR": true,
"maths": {
"score": 95,
"lastscore": 86
}
},
"2202": {
"name": "Sanket",
"maths": {
"score": 98,
"lastscore": 90
}
},
"2203": {
"name": "Ajit",
"maths": {
"score": 94,
"lastscore": 87
}
}
}
},
"1348": {
"schoolname": "Patil School",
"nameshort": "pat",
"students": {
"3201": {
"name": "Ravi",
"maths": {
"score": 95,
"lastscore": 86
}
},
"3202": {
"name": "Raj",
"isCR": true,
"maths": {
"score": 98,
"lastscore": 90
}
},
"3203": {
"name": "Ram",
"maths": {
"score": 94,
"lastscore": 87
}
}
}
}
}
}
I referenced How to parse dynamic JSON fields with GSON? .. but didn't work in my case .. I also have internal shared classes.
- I found a solution here on StackOverflow question . implements a deserializer for modeling classes like school and students.
source to share
You can just use java.util.Map
which is a key / value associative container where keys and values ββare arbitrary objects and can be consistent with dynamic JSON objects using Gson in a very straight forward manner. You just need to define the appropriate mappings (I made the field collapsed to save some visible space):
final class Response {
@SerializedName("schools") final HomeSchool school = null;
@SerializedName("school") final Map<Integer, School> schools = null;
}
final class HomeSchool {
@SerializedName("home") final int home = Integer.valueOf(0);
@SerializedName("statelevel") final int stateLevel = Integer.valueOf(0);
}
final class School {
@SerializedName("schoolname") final String name = null;
@SerializedName("nameshort") final String shortName = null;
@SerializedName("students") final Map<Integer, Student> students = null;
}
final class Student {
@SerializedName("name") final String name = null;
@SerializedName("isCR") final boolean isCr = Boolean.valueOf(false);
@SerializedName("maths") final Maths maths = null;
}
final class Maths {
@SerializedName("score") final int score = Integer.valueOf(0);
@SerializedName("lastscore") final int lastScore = Integer.valueOf(0);
}
Now that you have the mappings, you can deserialize your JSON easily:
private static final Gson gson = new Gson();
public static void main(final String... args) {
final Response response = gson.fromJson(JSON, Response.class);
for ( final Entry<Integer, School> schoolEntry : response.schools.entrySet() ) {
final School school = schoolEntry.getValue();
System.out.println(schoolEntry.getKey() + " " + school.name);
for ( final Entry<Integer, Student> studentEntry : school.students.entrySet() ) {
final Student student = studentEntry.getValue();
System.out.println("\t" + studentEntry.getKey()
+ " " + student.name
+ " CR:" + (student.isCr ? "+" : "-")
+ " (" + student.maths.score + ", " + student.maths.lastScore + ")"
);
}
}
}
1103 Indira School
2201 Ritesh CR: + (95, 86)
2202 Sanket CR: - (98, 90)
2203 Ajit CR: - (94, 87)
1348 Patil School
3201 Ravi CR: - (95, 86)
3202 Raj CR: + (98, 90)
3203 Ram CR: - (94, 87)
The type marker suggestions are partially correct: they are used to deserialize objects that you cannot or do not have specific mappings, such as lists of something or string maps. In your case, Gson just parses field declarations to resolve map types (both keys and values).
source to share
From Gson Documentation
Type mapType = new TypeToken<Map<Integer, Result> >() {}.getType(); // define generic type
Map<Integer, Result> result= gson.fromJson(new InputStreamReader(source), mapType);
source to share
Create a model object that implements JsonDeserializer
then you have this method to override:
@Override
public ActivityEvents deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
JsonObject jObject = jsonElement.getAsJsonObject();
for (Map.Entry<String, JsonElement> entry : jObject.entrySet()) {
entry.getKey(); //here you can get your key
gson.fromJson(entry.getValue(), StudebtInfo.class);; //here you can get value for key
}
}
source to share