2012-01-10 110 views
6

閱讀之前:我在此程序中使用了可下載的GSON庫。 http://webscripts.softpedia.com/script/Development-Scripts-js/Other-Libraries/Gson-71373.html使用GSON庫從URL(RESTful webservice)解析JSON字符串。 Android

我一直在努力,現在解析JSON相當長的一段時間,但每一次我嘗試從程序不「工作」的URL字符串。它不會失敗或關閉或發生錯誤。它只是不做解析。我的程序是爲了解析從http://api.geonames.org/weatherIcaoJSON?ICAO=LSZH&username=demo,並有一個更新按鈕再次運行解析過程,以便它會刷新信息。如果我使用硬編碼的JSON字符串,該程序完美工作。我甚至放入了應該從URL中檢索的字符串;但我似乎無法直接得到它。我正在使用GSON庫。

在代碼中,我提供了註釋來解釋我的思維過程。請注意,我有2種不同的方法試圖使用URL(我認爲也許原來的錯誤,所以我試圖使用另一個),這是我抓住吸管。請幫助我。謝謝。

我的代碼:

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

    } 
} 
+0

難道您發佈'Observation.java'? – curioustechizen 2012-01-10 15:41:29

+0

你是否證實'readURL'事實上會返回你期望的字符串? – 2012-01-10 16:39:16

回答

2

像謝爾蓋,我發現,在Android上所包含的JSON庫org.json.*簡單得多比GSON使用。

例如,在您的方案 - 你的JSON解析代碼應該是這樣的。

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

您也將受益於AsyncTaskThread。您永遠不想在UI線程上運行長時間運行的操作,因爲UI將顯示無響應和緩慢。

下面是關於如何使用AsyncTask來實現自己的目標的例子。瞭解更多關於它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); 
    } 
} 

,並執行你的任務,你應該運行在您的活動驗證碼。

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

注:此代碼是未經測試,但應該是一般的想法。

0

JSON響應通常gzip壓縮,試試這個在您的getJSONData()方法:

... ... 
uri = new URI(url); 
HttpGet method = new HttpGet(uri); // Get URI 
HttpResponse response = httpClient.execute(method); // Get response from method. 
InputStream in = response.getEntity().getContent(); 
GZIPInputStream gin = new GZIPInputStream(in); 
BufferedReader reader = new BufferedReader(new InputStreamReader(gin)); 
String line = null; 
while ((line = reader.readLine()) != null) { 
    jsonResponse.append(line); 
} 
reader.close(); 
... ...