Having trouble getting specific parameter from API

2019-08-23 02:49发布

I'm trying to make a simple weather app. I'm using this API for it. on that same page is a list of parameters in the JSON response. I can search for all the parameters and get a response except for the 'weather' parameter. every time I try that I get an

java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 3 path $[0]

error. I'm not sure what's causing it. here's my code.

public class Weather {

private String city;
private OWM owm = new OWM("8984d739fa91d7031fff0e84a3d2c520");
private CurrentWeather currentWeather;
private String weather;
private Clouds cloud;

public Weather() throws APIException {
    String API_KEY = "8984d739fa91d7031fff0e84a3d2c520";
    String Location = "Brooklyn";
    String urlString = "http://api.openweathermap.org/data/2.5/weather?q=" + Location
            + "&appid=" + API_KEY + "&units=imperial";

    try {
        StringBuilder result = new StringBuilder();
        URL url = new URL(urlString);
        URLConnection conn = url.openConnection();
        BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        String line;
        while ((line = rd.readLine()) != null){
            result.append(line);
        }
        rd.close();
        System.out.println(result);

        Map<String, Object> respMap = jsonToMap(result.toString());
        Map<String, Object> mainMap = jsonToMap(respMap.get("main").toString());
        Map<String, Object> windMap = jsonToMap(respMap.get("wind").toString());
        Map<String, Object> cloudsMap = jsonToMap(respMap.get("weather").toString());
// error is  here
        System.out.println("Current Temperature: " + mainMap.get("temp"));
        System.out.println("current humidity " + mainMap.get("humidity"));
        System.out.println("clouds " + respMap.get("description"));
      //  System.out.println("weather conditions: " + cloudsMap.get("main"));
// this always returns null 
        System.out.println("wind speeds " + windMap.get("speed"));
        System.out.println("wind angle: " + windMap.get("deg"));
    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
public static Map<String, Object> jsonToMap(String str){
    Map<String, Object> map = new Gson().fromJson(
           str, new TypeToken<HashMap<String, Object>>() {}.getType()
    );
    return map;
}

public String getCityName() {
    return cityName;
}
public int getCurrentWeather() throws APIException {
    owm.setUnit(OWM.Unit.IMPERIAL);
    currentWeather = owm.currentWeatherByCityName(this.cityName);
    return (int) Math.round(currentWeather.getMainData().getTemp());
}
public void setCityName(String cityName) {
    this.cityName = cityName;
}

public void setZipCode(String zipCode){
    this.zipCode = zipCode;
}
public String getZipCode(){
    return this.zipCode;
}
public String getWeather(){
    return this.weather;
}
}

I'm not really sure why that one parameter isn't working. I can search anything else fine, so why can't I search the weather parameter?

Edit: I'm doing this in my try/catch statement. it's giving me a NullPointerException

URL url = new URL(urlString);
            URLConnection conn = url.openConnection();
            conn.connect();

            JsonParser jp = new JsonParser();
            JsonElement root = jp.parse(new InputStreamReader((InputStream) conn.getContent()));
            JsonObject rootObj = root.getAsJsonObject();
            String description = rootObj.get("weather").getAsString();
// name of the array in the json
            System.out.println(description);

3条回答
干净又极端
2楼-- · 2019-08-23 03:25

The best way to parse the Json here is Gson Library Here first you can create pojo class of response you getting ,after that just pass the response String and get your output.

Gson gson=new Gson();
YourClass result=gson.fromjson(jsonString , YourClass.class);
查看更多
你好瞎i
3楼-- · 2019-08-23 03:36

Instead of blindly considering Hashmap for keyvalues, consider creating pojos, and then parse it. Create all PoJo for json.

Main.java

public class Weather {

    public static void main(String[] args) {


    String API_KEY = "8984d739fa91d7031fff0e84a3d2c520";
    String Location = "Brooklyn";
    String urlString = "http://api.openweathermap.org/data/2.5/weather?q=" + Location
            + "&appid=" + API_KEY + "&units=imperial";

    try {
        StringBuilder result = new StringBuilder();
        URL url = new URL(urlString);
        URLConnection conn = url.openConnection();
        BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        String line;
        while ((line = rd.readLine()) != null){
            result.append(line);
        }
        rd.close();
        System.out.println(result);
        com.google.gson.Gson gson=new Gson();
        Example finalResult=gson.fromJson(result.toString() , Example.class);
        System.out.println(finalResult.getMain().getTemp()); //56.26
        System.out.println(finalResult.getMain().getHumidity());  // 54
    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

}

Example.java (This pojo is for your json schema)

import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class Example {

@SerializedName("coord")
@Expose
private Coord coord;
@SerializedName("weather")
@Expose
private List<Weather> weather = null;
@SerializedName("base")
@Expose
private String base;
@SerializedName("main")
@Expose
private Main main;
@SerializedName("visibility")
@Expose
private Integer visibility;
@SerializedName("wind")
@Expose
private Wind wind;
@SerializedName("clouds")
@Expose
private Clouds clouds;
@SerializedName("dt")
@Expose
private Integer dt;
@SerializedName("sys")
@Expose
private Sys sys;
@SerializedName("timezone")
@Expose
private Integer timezone;
@SerializedName("id")
@Expose
private Integer id;
@SerializedName("name")
@Expose
private String name;
@SerializedName("cod")
@Expose
private Integer cod;

public Coord getCoord() {
return coord;
}

public void setCoord(Coord coord) {
this.coord = coord;
}

public List<Weather> getWeather() {
return weather;
}

public void setWeather(List<Weather> weather) {
this.weather = weather;
}

public String getBase() {
return base;
}

public void setBase(String base) {
this.base = base;
}

public Main getMain() {
return main;
}

public void setMain(Main main) {
this.main = main;
}

public Integer getVisibility() {
return visibility;
}

public void setVisibility(Integer visibility) {
this.visibility = visibility;
}

public Wind getWind() {
return wind;
}

public void setWind(Wind wind) {
this.wind = wind;
}

public Clouds getClouds() {
return clouds;
}

public void setClouds(Clouds clouds) {
this.clouds = clouds;
}

public Integer getDt() {
return dt;
}

public void setDt(Integer dt) {
this.dt = dt;
}

public Sys getSys() {
return sys;
}

public void setSys(Sys sys) {
this.sys = sys;
}

public Integer getTimezone() {
return timezone;
}

public void setTimezone(Integer timezone) {
this.timezone = timezone;
}

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Integer getCod() {
return cod;
}

public void setCod(Integer cod) {
this.cod = cod;
}

}

Coord.java


import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class Coord {

@SerializedName("lon")
@Expose
private Double lon;
@SerializedName("lat")
@Expose
private Double lat;

public Double getLon() {
return lon;
}

public void setLon(Double lon) {
this.lon = lon;
}

public Double getLat() {
return lat;
}

public void setLat(Double lat) {
this.lat = lat;
}

}

Weather.java

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class Weather {

@SerializedName("id")
@Expose
private Integer id;
@SerializedName("main")
@Expose
private String main;
@SerializedName("description")
@Expose
private String description;
@SerializedName("icon")
@Expose
private String icon;

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getMain() {
return main;
}

public void setMain(String main) {
this.main = main;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

public String getIcon() {
return icon;
}

public void setIcon(String icon) {
this.icon = icon;
}

}

Main.java

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class Main {

@SerializedName("temp")
@Expose
private Double temp;
@SerializedName("pressure")
@Expose
private Integer pressure;
@SerializedName("humidity")
@Expose
private Integer humidity;
@SerializedName("temp_min")
@Expose
private Integer tempMin;
@SerializedName("temp_max")
@Expose
private Double tempMax;

public Double getTemp() {
return temp;
}

public void setTemp(Double temp) {
this.temp = temp;
}

public Integer getPressure() {
return pressure;
}

public void setPressure(Integer pressure) {
this.pressure = pressure;
}

public Integer getHumidity() {
return humidity;
}

public void setHumidity(Integer humidity) {
this.humidity = humidity;
}

public Integer getTempMin() {
return tempMin;
}

public void setTempMin(Integer tempMin) {
this.tempMin = tempMin;
}

public Double getTempMax() {
return tempMax;
}

public void setTempMax(Double tempMax) {
this.tempMax = tempMax;
}

}

Wind.java

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class Wind {

@SerializedName("speed")
@Expose
private Double speed;
@SerializedName("deg")
@Expose
private Integer deg;

public Double getSpeed() {
return speed;
}

public void setSpeed(Double speed) {
this.speed = speed;
}

public Integer getDeg() {
return deg;
}

public void setDeg(Integer deg) {
this.deg = deg;
}

}

Clouds.java

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class Clouds {

@SerializedName("all")
@Expose
private Integer all;

public Integer getAll() {
return all;
}

public void setAll(Integer all) {
this.all = all;
}

}

Sys.java

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class Sys {

@SerializedName("type")
@Expose
private Integer type;
@SerializedName("id")
@Expose
private Integer id;
@SerializedName("message")
@Expose
private Double message;
@SerializedName("country")
@Expose
private String country;
@SerializedName("sunrise")
@Expose
private Integer sunrise;
@SerializedName("sunset")
@Expose
private Integer sunset;

public Integer getType() {
return type;
}

public void setType(Integer type) {
this.type = type;
}

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public Double getMessage() {
return message;
}

public void setMessage(Double message) {
this.message = message;
}

public String getCountry() {
return country;
}

public void setCountry(String country) {
this.country = country;
}

public Integer getSunrise() {
return sunrise;
}

public void setSunrise(Integer sunrise) {
this.sunrise = sunrise;
}

public Integer getSunset() {
return sunset;
}

public void setSunset(Integer sunset) {
this.sunset = sunset;
}

}

查看更多
smile是对你的礼貌
4楼-- · 2019-08-23 03:36

Map<String, Object> cloudsMap = jsonToMap(respMap.get("weather").toString());

This is the problem. You're trying to parse the weather property of the response as an object (a Map) but it's actually an array.

查看更多
登录 后发表回答