Use GSON to parse JSON feeds and get arrays instead of multi-parameters
I’m trying to parse the ELGG resfull web service ( on an Android app http://elgg.pro.tn/services/api/rest/json/?method=system.api.list )。
I’M USING THE GON LIBRARY TO CONVERT A JSON FEED TO A JAVA OBJECT, AND I CREATED ALL THE REQUIRED CLASSES FOR THE TRANSFORMATION (MAPPING).
The problem is with the jSON format (I can’t change it):
{
"status":0,
"result":{
"auth.gettoken":{
"description":"This API call lets a user obtain a user authentication token which can be used for authenticating future API calls. Pass it as the parameter auth_token",
"function":"auth_gettoken",
"parameters":{
"username":{
"type":"string",
"required":true
},
"password":{
"type":"string",
"required":true
}
},
"call_method":"POST",
"require_api_auth":false,
"require_user_auth":false
},
"blog.delete_post":{
"description":"Read a blog post",
"function":"blog_delete_post",
"parameters":{
"guid":{
"type":"string",
"required":true
},
"username":{
"type":"string",
"required":true
}
},
"call_method":"POST",
"require_api_auth":true,
"require_user_auth":false
}
}
}
The “result”
in this format contains many subitems that don’t have the same name (even though they have the same structure I call “apiMethod”), which GSON tries to resolve to detach objects, but what I want is that he resolves all the “result” subitems to “apiMethod” objects.
Solution
You can use a Map
to do this instead of an array if you don’t want to define all possible field purposes in Result
.
class MyResponse {
int status;
public Map<String, APIMethod> result;
}
class APIMethod {
String description;
String function;
etc
}
Otherwise you need to define a Result
object to use instead of Map
as a field for all possible “method” types, and use @SerializedName
due to comments for illegal Java names:
class Result {
@SerializedName("auth.gettoken")
APIMethod authGetToken;
@SerializedName("blog.delete_post")
APIMethod blogDeletePost;
etc
}
If you really want a List option, C is creating your own custom deserializer that passes the parsed JSON and creates an object with List
inside instead of a Map
or POJO.
class MyResponse {
public int status;
public List<APIMethod> methods;
public MyResponse(int status, List<APIMethod> methods) {
this.status = status;
this.methods = methods;
}
}
class MyDeserializer implements JsonDeserializer<MyResponse> {
public MyResponse deserialize(JsonElement je, Type type, JsonDeserializationContext jdc) throws JsonParseException
{
Gson g = new Gson();
List<APIMethod> list = new ArrayList<APIMethod>();
JsonObject jo = je.getAsJsonObject();
Set<Entry<String, JsonElement>> entrySet = jo.getAsJsonObject("result").entrySet();
for (Entry<String, JsonElement> e : entrySet) {
APIMethod m = g.fromJson(e.getValue(), APIMethod.class);
list.add(m);
}
return new MyResponse(jo.getAsJsonPrimitive("status").getAsInt(), list);
}
}
(Untested, but should work).
To use it, you need to register it:
Gson gson = new GsonBuilder()
.registerTypeAdapter(MyResponse.class, new MyDeserializer())
.create();