Skip to content

Use Gson to handle Rest Apis in your App

rutura edited this page Oct 16, 2017 · 6 revisions
  • GSon is a library by google that allows to parse Json responses from remote servers

  • It is usually paired with different http libraries to send POST and GET requests

  • We use Android AsyncHttp library (https://github.com/loopj/android-async-http) in this guide

  • Note that there are better ways to deal with Rest Apis on android such as Retrofit

  • This guide can server as a primary step to understanding the mechanics of how more complex libs like Retrofit work or in simple cases where you just want to just parse some JSON.

  • It is noteworthy also to remember that android provides native ways to parse json in the org.json package.

  • Add the dependencies to your project gradle file :

     compile 'com.google.code.gson:gson:2.8.0'
     compile 'com.loopj.android:android-async-http:1.4.9'

Be sure to check the latest versions for these libraries.

  • Be familiar with the rest api you want to use. This guide uses the rest APIs from github that are documented here https://developer.github.com/v3/ in particular we well be retrieving the repositories that below to the "blikoon" organization. The address to the API is https://api.github.com/orgs/blikoon/repos

  • If you try to perform the request to the API from clients like Postman you get a response like shown below (stripped down for clarity) :

   [
  {
    "id": 33164678,
    "name": "QtQREncoder",
    "full_name": "blikoon/QtQREncoder",
    
    }
  },
  {
    "id": 36174477,
    "name": "QtQRDecoder",
    "full_name": "blikoon/QtQRDecoder",
    
    }
  },
  {
    "id": 51284819,
    "name": "Imirire",
    "full_name": "blikoon/Imirire",
    
    }
  },
  {
    "id": 57352914,
    "name": "Rooster",
    "full_name": "blikoon/Rooster",
    
    }
  },
  {
    "id": 75274019,
    "name": "hidapi",
    "full_name": "blikoon/hidapi",
    
    }
  },
  {
    "id": 83015263,
    "name": "Ubufundi",
    
    }
  }
]

This response is directly returned as an array of repository objects.

  • Sometimes instead of being an array, the response is a plain object.Something like :
   repositories:[
  {
    "id": 33164678,
    "name": "QtQREncoder",
    "full_name": "blikoon/QtQREncoder",
    
    }
  },
  {
    "id": 36174477,
    "name": "QtQRDecoder",
    "full_name": "blikoon/QtQRDecoder",
    
    }
  },
  {
    "id": 51284819,
    "name": "Imirire",
    "full_name": "blikoon/Imirire",
    
    }
  },
  {
    "id": 57352914,
    "name": "Rooster",
    "full_name": "blikoon/Rooster",
    
    }
  },
  {
    "id": 75274019,
    "name": "hidapi",
    "full_name": "blikoon/hidapi",
    
    }
  },
  {
    "id": 83015263,
    "name": "Ubufundi",
    
    }
  }
]

Careful here, repositories is a key and the array on the right side of : is its value.We will see how you handle both of these cases ( response object and response array) .

  • Now that you know what your JSON response will look like ( our github api returns an array of repository objects),copy the full response from Postman or an equivalent and paste it in this jsonschema2pojo tool.Make sure to choose JSON and GSON as shown below. json2POJO
  • You can write your own class name and package, or leave them as defaults and edit them when we get to android studio. Your choice.
  • At the bottom click on the preview button and your JSON Schema classes are Generated.You see something like shown below but ofcourse it is your own classes pojo preview
  • For our guide here we name our Class Repo and the package is set to com.blikoon.gsonrest. Your choise.
  • The tool will generate three classes for us: Repo.java, Owner.java and Permissions.java. These classes provide necessary setters and getters to manipulate the different fields in your JSON response fields.
  • Create an Android studio project and create these separate classes.A complete project is shown here for reference.
  • Now how do we get our list of Repo objects in Java/Android code ? Here, again you need to think about the type of the response you got from the server : is it an Array of Objects or just an Object
  • If the response is an array of objects , you define a class like the one shown below:
     public class RepoResponse {
    public RepoResponse()
    {
    }
    public static List<Repo> parseJSON(String response) {
        Gson gson = new GsonBuilder().create();
        Type collectionType = new TypeToken<Collection<Repo>>(){}.getType();
        List<Repo> myRepos;
        myRepos = gson.fromJson(response, collectionType);
        return myRepos;
    }

}
  • The line
   Type collectionType = new TypeToken<Collection<Repo>>(){}.getType();

simply allows us to specify that we want to parse json and retrieve the result as a collection of Repo objects.Make sure to pass your own clas in where we passed "Repo". *We then use json to parse the response and return a list of Repo objects.

   List<Repo> myRepos;
   myRepos = gson.fromJson(response, collectionType);
   return myRepos

*Sometimes, the response from the server is a JSON object(just simple opbject).In that case your response will look something like

   public class RepoResponse {
    public RepoResponse()
    {
    }

    public static Repo parseJSON(String response) {
        Gson gson = new GsonBuilder().create();
        Repo repoResponse = gson.fromJson(response, Repo.class);
        return repoResponse;
    }

}
  • If the response is an object ,your RepoResponse class would look something like:
   public class RepoResponse {

    List<Repo> repositories;

    // public constructor is necessary for collections
    public RepoResponse() {
        repositories = new ArrayList<Repo>();
    }
	
	public static RepoResponse parseJSON(String response) {
        Gson gson = new GsonBuilder().create();
        RepoResponse repoResponse = gson.fromJson(response, RepoResponse.class);
        return repoResponse;
    }

}

Note that the "repositories" key matches the one in the object JSON response example we have shown above.

  • In this guide we use the array JSON response.Now the GSON building places are all in place. Next, we perfom the http response:
   client = new AsyncHttpClient();
   client.setUserAgent("RestApiTutorial");


   fetchButton = (Button) findViewById(R.id.fetchButton);
   fetchButton.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
      client.get(
      "https://api.github.com/orgs/blikoon/repos",
       new TextHttpResponseHandler() {
       @Override
       public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
          Log.d(LOGTAG,"request FAILED. ResponseString :"+ responseString + " Error : "+ throwable.getMessage());

          }

        @Override
        public void onSuccess(int statusCode, Header[] headers, String responseString) {
        Log.d(LOGTAG,"request SUCCEEDED.");
        List<Repo> orgList = RepoResponse.parseJSON(responseString);

        Log.d(LOGTAG," We got "+ orgList.size() + "Repos");
        for( Repo org :orgList)
        {
            Log.d(LOGTAG, "Repo :"+ org.getFullName());
        }
       }
      });
     }
    });
  • We instantiate an AsyncHttpClient and set the user agent.Github won't respond to you if you don't specify your user agent:
   client = new AsyncHttpClient();
   client.setUserAgent("RestApiTutorial");
  • And call get on the client, passing in the url of the api and TextHttpResponseHandler object callback that notifies us of success or error:
   client.get(
      "https://api.github.com/orgs/blikoon/repos",
      new TextHttpResponseHandler() {
      @Override
      public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
      Log.d(LOGTAG,"request FAILED. ResponseString :"+ responseString + " Error : "+ throwable.getMessage());

      }

      @Override
      public void onSuccess(int statusCode, Header[] headers, String responseString) {
      Log.d(LOGTAG,"request SUCCEEDED.");
      List<Repo> orgList = RepoResponse.parseJSON(responseString);

      Log.d(LOGTAG," We got "+ orgList.size() + "Repos");
      for( Repo org :orgList)
      {
        Log.d(LOGTAG, "Repo :"+ org.getFullName());
      }
    }
   });
Clone this wiki locally