Search code examples
androidjsonretrofitweather-api

Missing JSON Array with RetroFit 2.0 & WorldWeatherOnline API


I pulling data from a weather API, when I put the full url into my browser I get all the data, the structure is below:

{  
   "data":{  
      "current_condition":[  
         {  
            "cloudcover":"75",
            "FeelsLikeC":"0",
            "FeelsLikeF":"32",
            "humidity":"87",
            "observation_time":"10:29 PM",
            "precipMM":"0.0",
            "pressure":"1021",
            "temp_C":"4",
            "temp_F":"39",
            "visibility":"10",
            "weatherCode":"116",
            "weatherDesc":[  
               {  
                  "value":"Partly Cloudy"
               }
            ],
            "weatherIconUrl":[  
               {  
                  "value":"http:\/\/cdn.worldweatheronline.net\/images\/wsymbols01_png_64\/wsymbol_0004_black_low_cloud.png"
               }
            ],
            "winddir16Point":"SSW",
            "winddirDegree":"210",
            "windspeedKmph":"20",
            "windspeedMiles":"13"
         }
      ],
      "request":[  
         {  }
      ],
      "weather":[  
         {  
            "astronomy":[  ],
            "date":"2015-12-11",
            "hourly":[  
               {  },
               {  },
               {  },
               {  },
               {  },
               {  },
               {  },
               {  }
            ],
            "maxtempC":"8",
            "maxtempF":"46",
            "mintempC":"4",
            "mintempF":"38",
            "uvIndex":"0"
         }
      ]
   }
}

The hourly objects are minimised for space reasons.

My problem is that when I use this api call in my app via Retrofit 2.0, current_condition size is 0. Please see a screenshot of my debugger: enter image description here

My objects are correct, based on the return from the browser I have used http://www.jsonschema2pojo.org/ in order to obtain the correct structure and objects. My retrofit code is as follows:

public interface OpenWeatherApiInterface {

    @GET("?&format=json&num_of_days=5&key=API_KEY&")
    Call<OpenWeather> getWeatherForLocation(@Query("q") String city);
}

public class RestClient {

    private static OpenWeatherApiInterface mOpenWeatherApiInterface;
    private static String mBaseUrl = "http://api.worldweatheronline.com/free/v2/weather.ashx";


    public static OpenWeatherApiInterface getClient(){

        if(mOpenWeatherApiInterface==null){

            Retrofit client = new Retrofit.Builder()
                    .baseUrl(mBaseUrl)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();

            mOpenWeatherApiInterface = client.create(OpenWeatherApiInterface.class);
        }
        return mOpenWeatherApiInterface;
    }
}

Then in my main activity just to test this I call it as follows:

 Call<OpenWeather> call = RestClient.getClient().getWeatherForLocation("London");
    call.enqueue(new Callback<OpenWeather>() {
        @Override
        public void onResponse(Response<OpenWeather> response, Retrofit retrofit) {
            Log.i("Main Activity", response.body().toString());

            if (response.isSuccess()) {
                OpenWeather weather = response.body();
                Data data = weather.getData();
                List<CurrentCondition> conditionList = data.getCurrentCondition();
                Log.i("MainA", "blah");

            } else {
                try {
                    Log.i("Main Activity", response.errorBody().string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void onFailure(Throwable t) {
            Log.i("Main Activity", "Failure");
        }
    });

My class OpenWeather

public class OpenWeather {

    private Data data;
    private Map<String, Object> additionalProperties = new HashMap<String, Object>();

    /**
     *
     * @return
     * The data
     */
    public Data getData() {
        return data;
    }

    /**
     *
     * @param data
     * The data
     */
    public void setData(Data data) {
        this.data = data;
    }

    public Map<String, Object> getAdditionalProperties() {
        return this.additionalProperties;
    }

    public void setAdditionalProperty(String name, Object value) {
        this.additionalProperties.put(name, value);
    }
}

And my class Data:

public class Data {

    private List<CurrentCondition> currentCondition = new ArrayList<CurrentCondition>();
    private List<Request> request = new ArrayList<Request>();
    private List<Weather> weather = new ArrayList<Weather>();

    /**
     *
     * @return
     * The currentCondition
     */
    public List<CurrentCondition> getCurrentCondition() {
        return currentCondition;
    }

    /**
     *
     * @param currentCondition
     * The current_condition
     */
    public void setCurrentCondition(List<CurrentCondition> currentCondition) {
        this.currentCondition = currentCondition;
    }

    /**
     *
     * @return
     * The request
     */
    public List<Request> getRequest() {
        return request;
    }

    /**
     *
     * @param request
     * The request
     */
    public void setRequest(List<Request> request) {
        this.request = request;
    }

    /**
     *
     * @return
     * The weather
     */
    public List<Weather> getWeather() {
        return weather;
    }

    /**
     *
     * @param weather
     * The weather
     */
    public void setWeather(List<Weather> weather) {
        this.weather = weather;
    }
}

This is my first use of Retrofit and I find it strange that the array size is 0. I would've imagined I should get a crash if there was something wrong with the model

Can someone please help?


Solution

  • It is because you have different JSON key and Object property name. i.e current_condition json key should match key for Data class but your field name is currentCondition

    if you change it to

    public class Data {
    
    private List<CurrentCondition> current_condition
    

    I think it will work