Reading a JSON reply from WeatherUnderground

2020-02-16 01:05发布

package test;

import java.net.*;
import java.io.*;
import com.google.gson.*;
import com.google.gson.stream.JsonReader;

public class TestGson {

    URL callToApi;
//------------------------------------------------------------------------------
    public static void main(String[] args) {
        new TestGson();
    }
//------------------------------------------------------------------------------
    public TestGson(){
        try{
            sendCallToApi();
            readJson();
        }catch(IOException e){
            e.printStackTrace();
        }
    }
//------------------------------------------------------------------------------
    public void sendCallToApi(){
        try{
            callToApi = new URL("http://api.wunderground.com/api" +
                    "/[insert key here]" +
                    "/geolookup/conditions/forecast/q/" +
                    "Australia/" +
                    "Sydney.json");
        }catch(MalformedURLException e){
            e.printStackTrace();
        }
    }
//------------------------------------------------------------------------------
    public void readJson() throws IOException{
    Gson g = new Gson();
    InputStreamReader in = new InputStreamReader(callToApi.openStream());
    BufferedReader reader = new BufferedReader(in);
    String message = "hello";
    StringBuffer buf = new StringBuffer();

    while(message!=null){
        message = reader.readLine();
        buf.append(message);
    }
    message = buf.toString();
    String wdf = g.fromJson(message, String.class);
    System.out.println(wdf);
}
//------------------------------------------------------------------------------
}  



This is my first attempt at parsing JSON using GSON. I am simply making a call to the Weather Underground site asking them to send me the weather of Sydney, Australia.
However, I get multiple errors:

Exception in thread "main" com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected a string but was BEGIN_OBJECT at line 1 column 2
    at com.google.gson.Gson.fromJson(Gson.java:806)
    at com.google.gson.Gson.fromJson(Gson.java:761)
    at com.google.gson.Gson.fromJson(Gson.java:710)
    at com.google.gson.Gson.fromJson(Gson.java:682)
    at test.TestGson.readJson(TestGson.java:49)
    at test.TestGson.<init>(TestGson.java:19)
    at test.TestGson.main(TestGson.java:13)
Caused by: java.lang.IllegalStateException: Expected a string but was BEGIN_OBJECT at line 1 column 2
    at com.google.gson.stream.JsonReader.nextString(JsonReader.java:464)
    at com.google.gson.internal.bind.TypeAdapters$13.read(TypeAdapters.java:349)
    at com.google.gson.internal.bind.TypeAdapters$13.read(TypeAdapters.java:337)
    at com.google.gson.Gson.fromJson(Gson.java:795)
    ... 6 more

What is causing those errors? How do I properly make the call to the Weather Underground API to receive the weather info?

I tried this by modifying the example given on Mykong.com.

JSON Reply from Weather Underground

{   "response": {       "version": "0.1"        ,"termsofService": "http://www.wunderground.com/weather/api/d/terms.html"       ,"features": {      "geolookup": 1      ,       "conditions": 1     ,       "forecast": 1       }   }       ,   "location": {       "type":"INTLCITY",      "country":"SD",     "country_iso3166":"SA",     "country_name":"Saudi Arabia",      "state":"",     "city":"Jeddah",        "tz_short":"AST",       "tz_long":"Asia/Riyadh",        "lat":"21.67000008",        "lon":"39.15000153",        "zip":"00000",      "magic":"1",        "wmo":"41024",      "l":"/q/zmw:00000.1.41024",     "requesturl":"global/stations/41024.html",      "wuiurl":"http://www.wunderground.com/global/stations/41024.html",      "nearby_weather_stations": {        "airport": {        "station": [        { "city":"Jeddah King Abdul Aziz International Airport", "state":"", "country":"Saudi Arabia", "icao":"OEJN", "lat":"21.70000076", "lon":"39.18333435" },       { "city":"Jeddah", "state":"", "country":"SD", "icao":"OEJN", "lat":"21.67000008", "lon":"39.15000153" },       { "city":"Makkah", "state":"", "country":"SD", "icao":"OEMK", "lat":"21.43000031", "lon":"39.77000046" }        ]       }       ,       "pws": {        "station": [        ]       }       }   }       ,   "current_observation": {        "image": {      "url":"http://icons-ak.wxug.com/graphics/wu2/logo_130x80.png",      "title":"Weather Underground",      "link":"http://www.wunderground.com"        },      "display_location": {       "full":"Jeddah, Saudi Arabia",      "city":"Jeddah",        "state":"",     "state_name":"Saudi Arabia",        "country":"SD",     "country_iso3166":"SA",     "zip":"00000",      "latitude":"21.67000008",       "longitude":"39.15000153",      "elevation":"12.00000000"       },      "observation_location": {       "full":"Jeddah, ",      "city":"Jeddah",        "state":"",     "country":"SD",     "country_iso3166":"SA",     "latitude":"21.67000008",       "longitude":"39.15000153",      "elevation":"39 ft"     },      "estimated": {      },      "station_id":"OEJN",        "observation_time":"Last Updated on February 12, 9:00 AM AST",      "observation_time_rfc822":"Tue, 12 Feb 2013 09:00:00 +0300",        "observation_epoch":"1360648800",       "local_time_rfc822":"Tue, 12 Feb 2013 09:08:53 +0300",      "local_epoch":"1360649333",     "local_tz_short":"AST",     "local_tz_long":"Asia/Riyadh",      "local_tz_offset":"+0300",      "weather":"Clear",      "temperature_string":"77 F (25 C)",     "temp_f":77,        "temp_c":25,        "relative_humidity":"57%",      "wind_string":"From the North at 10 MPH",       "wind_dir":"North",     "wind_degrees":10,      "wind_mph":10,      "wind_gust_mph":0,      "wind_kph":17,      "wind_gust_kph":0,      "pressure_mb":"1011",       "pressure_in":"29.86",      "pressure_trend":"0",       "dewpoint_string":"61 F (16 C)",        "dewpoint_f":61,        "dewpoint_c":16,        "heat_index_string":"NA",       "heat_index_f":"NA",        "heat_index_c":"NA",        "windchill_string":"NA",        "windchill_f":"NA",     "windchill_c":"NA",     "feelslike_string":"77 F (25 C)",       "feelslike_f":"77",     "feelslike_c":"25",     "visibility_mi":"N/A",      "visibility_km":"N/A",      "solarradiation":"",        "UV":"-1",      "precip_1hr_string":"-9999.00 in (-9999.00 mm)",        "precip_1hr_in":"-9999.00",     "precip_1hr_metric":"-9999.00",     "precip_today_string":"0.00 in (0.0 mm)",       "precip_today_in":"0.00",       "precip_today_metric":"0.0",        "icon":"clear",     "icon_url":"http://icons-ak.wxug.com/i/c/k/clear.gif",      "forecast_url":"http://www.wunderground.com/global/stations/41024.html",        "history_url":"http://www.wunderground.com/history/airport/OEJN/2013/2/12/DailyHistory.html",       "ob_url":"http://www.wunderground.com/cgi-bin/findweather/getForecast?query=21.67000008,39.15000153"    }       ,   "forecast":{        "txt_forecast": {       "date":"3:00 AM AST",       "forecastday": [        {       "period":0,     "icon":"partlycloudy",      "icon_url":"http://icons-ak.wxug.com/i/c/k/partlycloudy.gif",       "title":"Tuesday",      "fcttext":"Clear in the morning, then partly cloudy. High of 84F. Breezy. Winds from the NNW at 10 to 20 mph.",     "fcttext_metric":"Clear in the morning, then partly cloudy. High of 29C. Breezy. Winds from the NNW at 15 to 30 km/h.",     "pop":"0"       }       ,       {       "period":1,     "icon":"clear",     "icon_url":"http://icons-ak.wxug.com/i/c/k/clear.gif",      "title":"Tuesday Night",        "fcttext":"Clear. Low of 70F. Winds from the NNW at 10 to 15 mph.",     "fcttext_metric":"Clear. Low of 21C. Breezy. Winds from the NNW at 15 to 25 km/h.",     "pop":"0"       }       ,       {       "period":2,     "icon":"partlycloudy",      "icon_url":"http://icons-ak.wxug.com/i/c/k/partlycloudy.gif",       "title":"Wednesday",        "fcttext":"Clear in the morning, then partly cloudy. High of 88F. Winds from the NNW at 5 to 15 mph.",      "fcttext_metric":"Clear in the morning, then partly cloudy. High of 31C. Breezy. Winds from the NNW at 10 to 25 km/h.",     "pop":"0"       }       ,       {       "period":3,     "icon":"clear",     "icon_url":"http://icons-ak.wxug.com/i/c/k/clear.gif",      "title":"Wednesday Night",      "fcttext":"Clear in the evening, then partly cloudy. Low of 70F. Winds from the NW at 5 to 15 mph.",        "fcttext_metric":"Clear in the evening, then partly cloudy. Low of 21C. Breezy. Winds from the NW at 10 to 25 km/h.",       "pop":"0"       }       ,       {       "period":4,     "icon":"partlycloudy",      "icon_url":"http://icons-ak.wxug.com/i/c/k/partlycloudy.gif",       "title":"Thursday",     "fcttext":"Clear in the morning, then partly cloudy. High of 88F. Winds from the North at 5 to 10 mph shifting to the WSW in the afternoon.",       "fcttext_metric":"Clear in the morning, then partly cloudy. High of 31C. Winds from the North at 5 to 15 km/h shifting to the WSW in the afternoon.",       "pop":"0"       }       ,       {       "period":5,     "icon":"clear",     "icon_url":"http://icons-ak.wxug.com/i/c/k/clear.gif",      "title":"Thursday Night",       "fcttext":"Clear. Low of 73F. Winds from the WNW at 5 to 10 mph.",      "fcttext_metric":"Clear. Low of 23C. Winds from the WNW at 5 to 15 km/h.",      "pop":"0"       }       ,       {       "period":6,     "icon":"clear",     "icon_url":"http://icons-ak.wxug.com/i/c/k/clear.gif",      "title":"Friday",       "fcttext":"Clear. High of 88F. Winds from the NNE at 5 to 10 mph shifting to the WSW in the afternoon.",        "fcttext_metric":"Clear. High of 31C. Winds from the NNE at 5 to 20 km/h shifting to the WSW in the afternoon.",        "pop":"0"       }       ,       {       "period":7,     "icon":"clear",     "icon_url":"http://icons-ak.wxug.com/i/c/k/clear.gif",      "title":"Friday Night",     "fcttext":"Clear. Low of 72F. Winds from the NW at 5 to 10 mph.",       "fcttext_metric":"Clear. Low of 22C. Winds from the NW at 5 to 15 km/h.",       "pop":"0"       }       ]       },      "simpleforecast": {     "forecastday": [        {"date":{   "epoch":"1360692000",   "pretty":"9:00 PM AST on February 12, 2013",    "day":12,   "month":2,  "year":2013,    "yday":42,  "hour":21,  "min":"00", "sec":0,    "isdst":"0",    "monthname":"February", "weekday_short":"Tue",  "weekday":"Tuesday",    "ampm":"PM",    "tz_short":"AST",   "tz_long":"Asia/Riyadh"},       "period":1,     "high": {       "fahrenheit":"84",      "celsius":"29"      },      "low": {        "fahrenheit":"70",      "celsius":"21"      },      "conditions":"Partly Cloudy",       "icon":"partlycloudy",      "icon_url":"http://icons-ak.wxug.com/i/c/k/partlycloudy.gif",       "skyicon":"mostlysunny",        "pop":0,        "qpf_allday": {     "in": 0.00,     "mm": 0.0       },      "qpf_day": {        "in": 0.00,     "mm": 0.0       },      "qpf_night": {      "in": 0.00,     "mm": 0.0       },      "snow_allday": {        "in": 0,        "cm": 0     },      "snow_day": {       "in": 0,        "cm": 0     },      "snow_night": {     "in": 0,        "cm": 0     },      "maxwind": {        "mph": 17,      "kph": 27,      "dir": "NW",        "degrees": 317      },      "avewind": {        "mph": 14,      "kph": 22,      "dir": "NW",        "degrees": 324      },      "avehumidity": 52,      "maxhumidity": 74,      "minhumidity": 43       }       ,       {"date":{   "epoch":"1360778400",   "pretty":"9:00 PM AST on February 13, 2013",    "day":13,   "month":2,  "year":2013,    "yday":43,  "hour":21,  "min":"00", "sec":0,    "isdst":"0",    "monthname":"February", "weekday_short":"Wed",  "weekday":"Wednesday",  "ampm":"PM",    "tz_short":"AST",   "tz_long":"Asia/Riyadh"},       "period":2,     "high": {       "fahrenheit":"88",      "celsius":"31"      },      "low": {        "fahrenheit":"70",      "celsius":"21"      },      "conditions":"Partly Cloudy",       "icon":"partlycloudy",      "icon_url":"http://icons-ak.wxug.com/i/c/k/partlycloudy.gif",       "skyicon":"partlycloudy",       "pop":0,        "qpf_allday": {     "in": 0.00,     "mm": 0.0       },      "qpf_day": {        "in": 0.00,     "mm": 0.0       },      "qpf_night": {      "in": 0.00,     "mm": 0.0       },      "snow_allday": {        "in": 0,        "cm": 0     },      "snow_day": {       "in": 0,        "cm": 0     },      "snow_night": {     "in": 0,        "cm": 0     },      "maxwind": {        "mph": 14,      "kph": 22,      "dir": "NW",        "degrees": 308      },      "avewind": {        "mph": 12,      "kph": 19,      "dir": "NW",        "degrees": 315      },      "avehumidity": 51,      "maxhumidity": 75,      "minhumidity": 39       }       ,       {"date":{   "epoch":"1360864800",   "pretty":"9:00 PM AST on February 14, 2013",    "day":14,   "month":2,  "year":2013,    "yday":44,  "hour":21,  "min":"00", "sec":0,    "isdst":"0",    "monthname":"February", "weekday_short":"Thu",  "weekday":"Thursday",   "ampm":"PM",    "tz_short":"AST",   "tz_long":"Asia/Riyadh"},       "period":3,     "high": {       "fahrenheit":"88",      "celsius":"31"      },      "low": {        "fahrenheit":"73",      "celsius":"23"      },      "conditions":"Partly Cloudy",       "icon":"partlycloudy",      "icon_url":"http://icons-ak.wxug.com/i/c/k/partlycloudy.gif",       "skyicon":"mostlysunny",        "pop":0,        "qpf_allday": {     "in": 0.00,     "mm": 0.0       },      "qpf_day": {        "in": 0.00,     "mm": 0.0       },      "qpf_night": {      "in": 0.00,     "mm": 0.0       },      "snow_allday": {        "in": 0,        "cm": 0     },      "snow_day": {       "in": 0,        "cm": 0     },      "snow_night": {     "in": 0,        "cm": 0     },      "maxwind": {        "mph": 9,       "kph": 14,      "dir": "West",      "degrees": 259      },      "avewind": {        "mph": 7,       "kph": 11,      "dir": "WSW",       "degrees": 250      },      "avehumidity": 51,      "maxhumidity": 69,      "minhumidity": 37       }       ,       {"date":{   "epoch":"1360951200",   "pretty":"9:00 PM AST on February 15, 2013",    "day":15,   "month":2,  "year":2013,    "yday":45,  "hour":21,  "min":"00", "sec":0,    "isdst":"0",    "monthname":"February", "weekday_short":"Fri",  "weekday":"Friday", "ampm":"PM",    "tz_short":"AST",   "tz_long":"Asia/Riyadh"},       "period":4,     "high": {       "fahrenheit":"88",      "celsius":"31"      },      "low": {        "fahrenheit":"72",      "celsius":"22"      },      "conditions":"Clear",       "icon":"clear",     "icon_url":"http://icons-ak.wxug.com/i/c/k/clear.gif",      "skyicon":"mostlysunny",        "pop":0,        "qpf_allday": {     "in": 0.00,     "mm": 0.0       },      "qpf_day": {        "in": 0.00,     "mm": 0.0       },      "qpf_night": {      "in": 0.00,     "mm": 0.0       },      "snow_allday": {        "in": 0,        "cm": 0     },      "snow_day": {       "in": 0,        "cm": 0     },      "snow_night": {     "in": 0,        "cm": 0     },      "maxwind": {        "mph": 10,      "kph": 16,      "dir": "WSW",       "degrees": 248      },      "avewind": {        "mph": 7,       "kph": 11,      "dir": "WSW",       "degrees": 248      },      "avehumidity": 53,      "maxhumidity": 60,      "minhumidity": 38       }       ]       }   }}null

1条回答
2楼-- · 2020-02-16 01:47

You don't seem to understand what Gson does. It's a JSON parser, specifically one that will deserialize JSON to a Java POJO.

In your code you have:

String wdf = g.fromJson(message, String.class);

You're telling Gson to deserialize the JSON to a Java String object. It can't do that; your JSON isn't a String object - it's a big JSON object returned from Weather Underground. You already have a Java String (message) that contains the JSON text itself.

You either need to create a POJO that the JSON can be deserialized to, or pick the parts out of the JSON you want using Gson's parser and associated objects/methods.

Here's the start of what a POJO would look like (all fields public with no getters/setters just to make this example small):

class MyWUPojo {
    public Response response;
    // more after this that match the JSON
}

class Response {
    public String version;
    public String termsofservice;
    public Map<String, Integer> features;
}

You'd then deserialize the JSON into an instance of MyWUPojo with:

MyWUPojo wup = new Gson().fromJson(message,MyWUPojo.class);

If you didn't want to go the POJO route you could parse the JSON then get what you want from it:

JsonObject o = (JsonObject) new JsonParser().parse(message);

Now you' can use the various methods of JsonObject to access the parsed JSON. (See: http://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/JsonObject.html )

The GSON User's Guide is pretty well written and explains this and more in great detail.

Edit to add: That null at the end of your JSON is caused by this:

while(message!=null){
    message = reader.readLine();
    buf.append(message);
}

You append null then the loop exits. It needs to be:

while ((message = reader.readline()) != null) {
    buf.append(message);
}
查看更多
登录 后发表回答