Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parsing JSON string from URL (RESTful webservice) using GSON libraries. Android

Before reading: I used downloadable GSON libraries in this program. http://webscripts.softpedia.com/script/Development-Scripts-js/Other-Libraries/Gson-71373.html

I've been trying to parse JSON for quite some time now but every time I try to get the string from the URL the program doesn't "work". It doesn't fail or close down or get errors. It just doesn't do the parse. My program is meant to parse from http://api.geonames.org/weatherIcaoJSON?ICAO=LSZH&username=demo and has a button to update run the parsing process again so that it would refresh the information. If I use a hardcoded JSON string, the program works perfectly. I even put in the string that is supposed to be retrieved from the URL; but I can't seem to be able to get it directly. I am using GSON libraries.

In the code, I've provided comments to explain my thought process. Note that I have 2 different methods that are trying to use the URL (i thought that the maybe the original one was wrong so i tried to use another one), this was me grasping at straws. Please help me out. Thank you.

My Code:

package com.android.testgson;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URI;
import java.net.URL;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.google.gson.Gson;

public class GSONTestActivity extends Activity {
    /** Called when the activity is first created. */

    //String test = "";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        TextView tv = (TextView)findViewById(R.id.textViewInfo);
        syncButtonClickListener();

        runJSONParser(tv);

    }

    private void syncButtonClickListener() 
    {

        Button syncButton = (Button)findViewById(R.id.buttonSync);
        syncButton.setOnClickListener(new View.OnClickListener() 
        {
            public void onClick(View v) 
            {
                TextView tv = (TextView)findViewById(R.id.textViewInfo);
                runJSONParser(tv);
            }
        });
    }


    public InputStream getJSONData(String url){
        // create DefaultHttpClient
        HttpClient httpClient = new DefaultHttpClient();
        URI uri; // for URL
        InputStream data = null; // for URL's JSON

        try {
            uri = new URI(url);
            HttpGet method = new HttpGet(uri); // Get URI
            HttpResponse response = httpClient.execute(method); // Get response from method.  
            data = response.getEntity().getContent(); // Data = Content from the response URL. 
        } catch (Exception e) {
            e.printStackTrace();
        }

        return data;
    }

    public void runJSONParser(TextView tv){
        try{
            Gson gson = new Gson();
            //Reader r = new InputStreamReader(getJSONData("http://api.geonames.org/weatherIcaoJSON?ICAO=LSZH&username=demo"));
            /**I tried parsing the URL, but it didn't work. No error messages, just didn't parse.*/
            //Reader r = new InputStreamReader(getJSONData("android.resource://"+ getPackageName() + "/" + R.raw.yourparsable));
            /**I tried parsing from local JSON file. Didn't work. Again no errors. The program simply stalls. */

            //String testString = "{\"weatherObservation\":{\"clouds\":\"few clouds\",\"weatherCondition\":\"n/a\",\"observation\":\"LSZH 041320Z 24008KT 210V270 9999 FEW022 SCT030 BKN045 05/01 Q1024 NOSIG\",\"windDirection\":\"240\",\"ICAO\":\"LSZH\",\"elevation\":\"432\",\"countryCode\":\"CH\",\"lng\":\"8.516666666666667\",\"temperature\":\"5\",\"dewPoint\":\"1\",\"windSpeed\":\"08\",\"humidity\":\"75\",\"stationName\":\"Zurich-Kloten\",\"datetime\":\"2012-01-04 13:20:00\",\"lat\":\"47.46666666666667\",\"hectoPascAltimeter\":\"1024\"}}";
            /**If I parse this string. The parser works. It is the same exact string like in the URL.*/
            //String failString = "{\"status\":{\"message\":\"the hourly limit of 2000 credits demo has been exceeded. Please throttle your requests or use the commercial service.\",\"value\":19}}";
            /**Even if the url delivers this string (because the hourly limit would be reached), the string is still parsed correctly.*/
            String json = readUrl("http://api.geonames.org/weatherIcaoJSON?ICAO=LSZH&username=demo");
            /**At this point I tried a different means of accessing the URL but still I had the exact same problem*/

            Observation obs = gson.fromJson(json, Observation.class);
            // "json" can be replaced with r, testString, failString to see all my previous results.

            if (obs.getWeatherObservation()!=null)
            {
                tv.setText("Clouds - " + obs.getWeatherObservation().getClouds()
                        + "\nTemperature - " + obs.getWeatherObservation().getTemperature()
                        + "\nWind Speed - " + obs.getWeatherObservation().getWindSpeed()
                        + "\nHumidity - " + obs.getWeatherObservation().getHumidity());
            }
            else if (obs.getStatus()!=null)
            {
                tv.setText("Message - " + obs.getStatus().getMessage()
                        + "\nValue - " + obs.getStatus().getValue());
            }

        }catch(Exception ex){
            ex.printStackTrace();
        }

    }

    public static String readUrl(String urlString) throws Exception {
        BufferedReader reader = null;

        try{
            URL url = new URL(urlString);
            reader = new BufferedReader(new InputStreamReader (url.openStream()));
            StringBuffer buffer = new StringBuffer();
            int read;
            char[]chars = new char[1024];
            while ((read = reader.read(chars)) != -1)
                buffer.append(chars, 0, read); 

            return buffer.toString();
        } finally {
            if (reader != null)
                reader.close();
        }

    }
}
like image 957
user1028408 Avatar asked Jan 10 '12 15:01

user1028408


1 Answers

Like Sergey, I've found that the included json library org.json.* on Android is far simpler to use than GSON.

For example, in your scenario - your JSON parsing code would look like this.

String jsonData = readUrl("http://api.geonames.org/weatherIcaoJSON?ICAO=LSZH&username=demo");
JSONObject weatherJSONObject = new JSONObject( jsonData );

try {
    // Not sure the format of your data, but you would want something like this
    String clouds = weatherJSONObject.getString("clouds");
} catch (JSONException e) {
    e.printStackTrace();
}

You would also benefit from AsyncTask or Thread. You never want to run long running operations on the UI thread because the UI will appear unresponsive and sluggish.

Below is an example on how you can use AsyncTask to achieve your goal. Read more about it here

private class FetchJSONDataTask extends AsyncTask<String, Void, JSONObject> {

     // This gets executed on a background thread
     protected JSONObject doInBackground(String... params) {
         String urlString = params[0];
         String jsonData = readUrl( urlString );
         JSONObject weatherJSONObject = new JSONObject( jsonData );
         return weatherJSONObject;
     }

     // This gets executed on the UI thread
     protected void onPostExecute(JSONObject json) {
         //Your function that takes a json object and populates views
         setUpViews( json );
     }
 }

And to execute your task, you should run this code in your activity.

FetchJSONDataTask task = new FetchJSONDataTask();
task.execute( new String[] { "http://api.geonames.org/weatherIcaoJSON?ICAO=LSZH&username=demo" } );

Note: This code is untested, but that should be the general idea.

like image 117
Kiran Ryali Avatar answered Nov 04 '22 08:11

Kiran Ryali