Получить данные из вложенного объекта Json
Имеется такой Json файл
{
"coord": {
"lon": 47.5,
"lat": 42.98
},
"weather": [
{
"id": 802,
"main": "Clouds",
"description": "scattered clouds",
"icon": "03n"
}
],
"base": "stations",
"main": {
"temp": 15.28,
"feels_like": 14.85,
"temp_min": 15,
"temp_max": 15.56,
"pressure": 1014,
"humidity": 87
},
"visibility": 10000,
"wind": {
"speed": 2,
"deg": 140
},
"clouds": {
"all": 37
},
"dt": 1589559748,
"sys": {
"type": 1,
"id": 8965,
"country": "RU",
"sunrise": 1589506004,
"sunset": 1589558769
},
"timezone": 10800,
"id": 532096,
"name": "Makhachkala",
"cod": 200
}
Мне оттуда нужны description, который находится внутри weather, temp, который находится внутри main, humidity, который находится внутри temp, и name в конце списка
POJO класс (если закомментировать все поля и методы кроме location и getLocation, то я получаю местоположение. В противном случае ничего не получаю)
public class WeatherLocation {
@SerializedName("name")
@Expose
private String location;
@SerializedName("main")
@Expose
private WeatherTemp weatherTemp;
@SerializedName("weather")
@Expose
private WeatherDescription weatherDescription;
public String getLocation() {
return location;
}
public WeatherTemp getWeatherTemp() {
return weatherTemp;
}
public WeatherDescription getWeatherDescription() {
return weatherDescription;
}
}
POJO класс 2
public class WeatherTemp {
@SerializedName("temp")
@Expose
private int temp;
@SerializedName("humidity")
@Expose
private int humidity;
public int getTemp() {
return temp;
}
public int getHumidity() {
return humidity;
}
}
POJO класс 3
public class WeatherTemp {
@SerializedName("temp")
@Expose
private int temp;
@SerializedName("humidity")
@Expose
private int humidity;
public int getTemp() {
return temp;
}
public int getHumidity() {
return humidity;
}
}
MainActivity
NetworkRequest.getRequest()
.getWeatherApi()
.getWeather()
.enqueue(new Callback<WeatherLocation>() {
@Override
public void onResponse(Call<WeatherLocation> call, Response<WeatherLocation> response) {
WeatherLocation weatherLocation = response.body();
tvLocation.setText(weatherLocation.getLocation());
tvTemperature.setText(weatherLocation.getWeatherTemp().getTemp());
tvDescription.setText(weatherLocation.getWeatherDescription().getDescription());
tvHumidity.setText(weatherLocation.getWeatherTemp().getHumidity());
}
@Override
public void onFailure(Call<WeatherLocation> call, Throwable t) {
}
});
}
В итоге я получаю данные только от getLocale. При получении остальных выбрасывается исключение
Ответы (1 шт):
Я бы предложил сделать класс который будет отвечать за поля которые вам нужны. Вероятнее всего они есть, но вы получаете не массив а только один объект. То есть например, вместо массива "weather" вы получаете только один объект который противоречит тому что приходит. Поэтому делаем класс для json weather:
"weather": [
{
"id": 802,
"main": "Clouds",
"description": "scattered clouds",
"icon": "03n"
}
],
public class Weather {
private Integer id;
private String main;
private String description;
private String icon;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Weather withId(Integer id) {
this.id = id;
return this;
}
public String getMain() {
return main;
}
public void setMain(String main) {
this.main = main;
}
public Weather withMain(String main) {
this.main = main;
return this;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Weather withDescription(String description) {
this.description = description;
return this;
}
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
public Weather withIcon(String icon) {
this.icon = icon;
return this;
}
}
и дальше есть вместо этого варианта:
@SerializedName("weather")
@Expose
private WeatherDescription weatherDescription;
делаем так:
private ArrayList<Weather> weatherDescription;
то есть вы будете ждать массив объектов класса Weather. Для генерации класса использовал этот инструмент. И дальше после получения ответа вы можете получить массив. Так же советую добавить условие isSuccessful для response:
if(response.isSuccessful){
//обрабатываем то что пришло
}
таким образом вы сможете предотвратить ошибку если сервер вернет не 200 ответ. И собственно дальше получаем массив weather:
if(response.isSuccessful){
WeatherLocation weatherLocation = response.body();
ArrayList<Weather> weatherDescr = weatherLocation.getWeatherDescription()
for(i in 0 until weatherDescr.size){
// получаем элементы массива описания погоды
Weather weather = weatherDescr[i]
weather.description // получили описание
}
}
получение "main" будет происходить немного по другому сценарию. Вы получаете jsonObject. А значит его нужно будет конвертировать в класс. Я бы вам советовал в главном классе ответа WeatherLocation вместо поля:
@SerializedName("main")
@Expose
private WeatherTemp weatherTemp;
использовать другой тип данных:
private JsonObject main;
таким образом вы сможете получить json который пришел с сервера. Следующим этапом будет его конвертация в объект класса который вы создали. Для начала получим его из response:
weatherLocation.getMain()
и дальше конвертация будет происходить так:
Gson gson = new Gson();
WeatherTemp tempClass= gson.fromJson(json, WeatherTemp.class);
ну и дальше уже можно будет получать переменные из объекта класса.