Разбор строки JSON из URL (веб-сервис RESTful) с использованием библиотек GSON. Android - PullRequest
6 голосов
/ 10 января 2012

Перед прочтением: в этой программе я использовал загружаемые библиотеки GSON.http://webscripts.softpedia.com/script/Development-Scripts-js/Other-Libraries/Gson-71373.html

Я уже довольно давно пытаюсь проанализировать 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();
        }

    }
}

Ответы [ 3 ]

2 голосов
/ 10 января 2012

Как и Сергей, я обнаружил, что включенная библиотека json org.json.* на Android гораздо проще в использовании, чем GSON.

Например, в вашем сценарии - ваш код синтаксического анализа JSON будет выглядеть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();
}

Вы также выиграете от AsyncTask или Thread.Вы никогда не захотите запускать длительные операции в потоке пользовательского интерфейса, потому что пользовательский интерфейс будет не отвечать на запросы и работать медленно.

Ниже приведен пример того, как вы можете использовать AsyncTask для достижения своей цели.Подробнее об этом здесь

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 голосов
/ 11 января 2012

JSON-ответ обычно отправляется в архиве, попробуйте это в вашем методе 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();
... ...
0 голосов
/ 10 января 2012

Я выполнил анализ json с помощью org.json. *

http://www.json.org/java/index.html Документы в Android 4. http://developer.android.com/reference/org/json/package-summary.html (как пример)

Вы можете скачать jar отсюда http://repo1.maven.org/maven2/org/json/json/20090211/json-20090211.jar

Я бы также рассмотрел запуск ваших http-запросов в другом потоке и только затем перерисовывал ваш пользовательский интерфейс.Читайте об android.os.Handler тоже для этой цели.

спасибо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...