Как получить ArrayList из JSONObject?
Пытаюсь получить массив данных из json по ссылке: https://api.ratesapi.io/api/latest и преобразовать его в ArrayList<Currency>. Класс Currency выглядит так:
public class Currency {
private String name;
private double rate;
}
Полученный json выглядит так:
{"base":"EUR","rates":{"GBP":0.90155,"HKD":9.1166,"IDR":17221.03,
"ILS":4.0124,"DKK":7.4479,"INR":88.1125,"CHF":1.079,"MXN":26.3047,
"CZK":26.183,"SGD":1.6158,"THB":36.63,"HRK":7.4828,"MYR":4.9352,
"NOK":10.629,"CNY":8.2003,"BGN":1.9558,"PHP":57.787,"SEK":10.2805,
"PLN":4.4021,"ZAR":20.8452,"CAD":1.5739,"ISK":160.6,"BRL":6.3697,
"RON":4.836,"NZD":1.784,"TRY":8.6055,"JPY":124.74,"RUB":86.6154,
"KRW":1396.28,"USD":1.1763,"HUF":345.19,"AUD":1.6445},"date":"2020-08-10"}
С помощью org.json записываю данные в JSONObject:
JSONObject object = new JSONObject(getJSON("https://api.ratesapi.io/api/latest"));
Затем пытаюсь преобразовать объект JSONObject в массив JSONArray:
JSONArray array = object.getJSONArray("rates");
Этот код выдает ошибку:
Exception in thread "main" org.json.JSONException: JSONObject["rates"]
is not a JSONArray.
Что я делаю не так? Каким образом получить ArrayList из строки json?
Есть подозрение, что проблема в отсутствии квадратных скобок в строке json.
Ответы (2 шт):
Посмотрите внимательно на исходный JSON, все дело в том, что в нем не List, а Map, посему при попытке преобразовать это в лист вы получаете вполне справедливое исключение. Я думаю, что вы без труда разберете этот код и поймете в чем проблема:
List<Currency> result = object.getJSONObject("rates").toMap().entrySet().stream()
.map(e -> new Currency(e.getKey(), Double.valueOf(e.getValue().toString())))
.collect(Collectors.toList());
И сам класс Currency с конструктором:
class Currency {
private String name;
private double rate;
public Currency(String name, double rate) {
this.name = name;
this.rate = rate;
}
}
Для получения json из URL и преобразования его в объект можно использовать ObjectMapper. В данном случае (если структура json всегда одинакова) это может быть Map<String, Object>.
ObjectMapper mapper = new ObjectMapper();
URL url = new URL("https://api.ratesapi.io/api/latest");
Map<String, Object> map = mapper.readValue(url, Map.class);
System.out.println(map);
// {base=EUR, rates={GBP=0.89843, HKD=9.132, ... , AUD=1.6406}, date=2020-08-11}
Получаем из этой карты внутреннюю карту rates:
Map<String, Double> rates = (Map<String, Double>) map.get("rates");
System.out.println(rates); // {GBP=0.89843, HKD=9.132, ... , AUD=1.6406}
Преобразовываем карту Map<String, Double> в ArrayList<Currency>:
ArrayList<Currency> list = rates.entrySet().stream()
.map(entry -> new Currency(entry.getKey(), entry.getValue()))
.collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
System.out.println(list); // [GBP=0.89843, HKD=9.132, ... , AUD=1.6406]
Замечание: добавляем конструктор с двумя полями name и rate;
Замечание: переопределяем метод toString так: shortName + "=" + rate;
Зависимость Maven:
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.11.2</version>
</dependency>