Java – Use GSON to parse JSON feeds and get arrays instead of multi-parameters

Use GSON to parse JSON feeds and get arrays instead of multi-parameters… here is a solution to the problem.

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

Related Problems and Solutions