How to send POST request in JSON using HTTPClient in Android?

In this answer I am using an example posted by Justin Grammens.

About JSON

JSON stands for JavaScript Object Notation. In JavaScript properties can be referenced both like this object1.name and like this object['name'];. The example from the article uses this bit of JSON.

The Parts
A fan object with email as a key and [email protected] as a value

{
  fan:
    {
      email : '[email protected]'
    }
}

So the object equivalent would be fan.email; or fan['email'];. Both would have the same value of '[email protected]'.

About HttpClient Request

The following is what our author used to make a HttpClient Request. I do not claim to be an expert at all this so if anyone has a better way to word some of the terminology feel free.

public static HttpResponse makeRequest(String path, Map params) throws Exception 
{
    //instantiates httpclient to make request
    DefaultHttpClient httpclient = new DefaultHttpClient();

    //url with the post data
    HttpPost httpost = new HttpPost(path);

    //convert parameters into JSON object
    JSONObject holder = getJsonObjectFromMap(params);

    //passes the results to a string builder/entity
    StringEntity se = new StringEntity(holder.toString());

    //sets the post request as the resulting string
    httpost.setEntity(se);
    //sets a request header so the page receving the request
    //will know what to do with it
    httpost.setHeader("Accept", "application/json");
    httpost.setHeader("Content-type", "application/json");

    //Handles what is returned from the page 
    ResponseHandler responseHandler = new BasicResponseHandler();
    return httpclient.execute(httpost, responseHandler);
}

Map

If you are not familiar with the Map data structure please take a look at the Java Map reference. In short, a map is similar to a dictionary or a hash.

private static JSONObject getJsonObjectFromMap(Map params) throws JSONException {

    //all the passed parameters from the post request
    //iterator used to loop through all the parameters
    //passed in the post request
    Iterator iter = params.entrySet().iterator();

    //Stores JSON
    JSONObject holder = new JSONObject();

    //using the earlier example your first entry would get email
    //and the inner while would get the value which would be '[email protected]' 
    //{ fan: { email : '[email protected]' } }

    //While there is another entry
    while (iter.hasNext()) 
    {
        //gets an entry in the params
        Map.Entry pairs = (Map.Entry)iter.next();

        //creates a key for Map
        String key = (String)pairs.getKey();

        //Create a new map
        Map m = (Map)pairs.getValue();   

        //object for storing Json
        JSONObject data = new JSONObject();

        //gets the value
        Iterator iter2 = m.entrySet().iterator();
        while (iter2.hasNext()) 
        {
            Map.Entry pairs2 = (Map.Entry)iter2.next();
            data.put((String)pairs2.getKey(), (String)pairs2.getValue());
        }

        //puts email and '[email protected]'  together in map
        holder.put(key, data);
    }
    return holder;
}

Please feel free to comment on any questions that arise about this post or if I have not made something clear or if I have not touched on something that your still confused about... etc whatever pops in your head really.

(I will take down if Justin Grammens does not approve. But if not then thanks Justin for being cool about it.)

Update

I just happend to get a comment about how to use the code and realized that there was a mistake in the return type. The method signature was set to return a string but in this case it wasnt returning anything. I changed the signature to HttpResponse and will refer you to this link on Getting Response Body of HttpResponse the path variable is the url and I updated to fix a mistake in the code.


I recommend using this HttpURLConnectioninstead HttpGet. As HttpGet is already deprecated in Android API level 22.

HttpURLConnection httpcon;  
String url = null;
String data = null;
String result = null;
try {
  //Connect
  httpcon = (HttpURLConnection) ((new URL (url).openConnection()));
  httpcon.setDoOutput(true);
  httpcon.setRequestProperty("Content-Type", "application/json");
  httpcon.setRequestProperty("Accept", "application/json");
  httpcon.setRequestMethod("POST");
  httpcon.connect();

  //Write       
  OutputStream os = httpcon.getOutputStream();
  BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
  writer.write(data);
  writer.close();
  os.close();

  //Read        
  BufferedReader br = new BufferedReader(new InputStreamReader(httpcon.getInputStream(),"UTF-8"));

  String line = null; 
  StringBuilder sb = new StringBuilder();         

  while ((line = br.readLine()) != null) {  
    sb.append(line); 
  }         

  br.close();  
  result = sb.toString();

} catch (UnsupportedEncodingException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
} 

Here is an alternative solution to @Terrance's answer. You can easly outsource the conversion. The Gson library does wonderful work converting various data structures into JSON and the other way around.

public static void execute() {
    Map<String, String> comment = new HashMap<String, String>();
    comment.put("subject", "Using the GSON library");
    comment.put("message", "Using libraries is convenient.");
    String json = new GsonBuilder().create().toJson(comment, Map.class);
    makeRequest("http://192.168.0.1:3000/post/77/comments", json);
}

public static HttpResponse makeRequest(String uri, String json) {
    try {
        HttpPost httpPost = new HttpPost(uri);
        httpPost.setEntity(new StringEntity(json));
        httpPost.setHeader("Accept", "application/json");
        httpPost.setHeader("Content-type", "application/json");
        return new DefaultHttpClient().execute(httpPost);
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

Similar can be done by using Jackson instead of Gson. I also recommend taking a look at Retrofit which hides a lot of this boilerplate code for you. For more experienced developers I recommend trying out RxAndroid.