Вот json в котором каждый раз появляются новые пары ключ-значение, их то больше , то меньше. Я хочу добавить каждую пару в отдельную ModelData(String, Double).
Вот до чего дошел : Type type = new TypeToken<ModelData>(){}.getType();
Далее ModelData myData = GSON.fromJson() но что подать на вход. Он хочет JsonReader и type. А JsonReader в свою очередь требует Reader. Как сделать Reader , если имеется только json объект.
И на правильном ли я вообще пути?
У меня подключена библиотека json-simple и GSON
Попробовал такое
Type type = new TypeToken<ModelData>(){}.getType();
ModelData myData = GSON.fromJson(json,type);
но не получаю чего то похожего на то, что получается , если использовать вместо ModelDate Map <'String, Double>.
{
"base": "EUR",
"date": "2017-12-06",
"rates": {
"AUD": 1.5565,
"BGN": 1.9558,
"BRL": 3.8193,
"CAD": 1.4963,
"CHF": 1.1678,
"CNY": 7.8169,
"CZK": 25.636,
"DKK": 7.4421,
"GBP": 0.88335,
"HKD": 9.2323,
"HRK": 7.5463,
"HUF": 314.45,
"IDR": 16007,
"ILS": 4.1519,
"INR": 76.243,
"JPY": 132.52,
"KRW": 1291.5,
"MXN": 22.203,
"MYR": 4.816,
"NOK": 9.7575,
"NZD": 1.7141,
"PHP": 59.891,
"PLN": 4.2142,
"RON": 4.632,
"RUB": 69.791,
"SEK": 9.9265,
"SGD": 1.5925,
"THB": 38.559,
"TRY": 4.5489,
"USD": 1.1817,
"ZAR": 15.985
}
}
.Тут я получаю rates который хочу в массив ModelData.
Object obj = new Object();
try {
// Считываем json
obj = new JSONParser().parse(answer);
} catch (Exception e) {
}
JSONObject jo = (JSONObject) obj;
String Currency = (String) jo.get("base");
String Date = (String) jo.get("date");
JSONObject rates = (JSONObject) jo.get("rates");
Gson gson = new GsonBuilder()
.registerTypeAdapter(ModelData.class,new DeserializerCurrency())
.create();
ModelData modelData = gson.fromJson(rates.toJSONString(),ModelData.class);
.
class ModelData {
private String name;
private Double value;
ModelData(String name, Double value) {
this.name = name;
this.value = value;
}
String getName() {
return this.name;
}
Double getValue() {
return this.value;
}
}
.
public class DeserializerCurrency implements JsonDeserializer<ModelData> {
@Override
public ModelData deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
System.out.println("ДЕсериализатор");
ModelData modelData = null;
if(json.isJsonObject()){
Set<Map.Entry<String,JsonElement>> entrySet = json.getAsJsonObject().entrySet();
System.out.println("Размер" + entrySet.size());
if(entrySet.size() > 0){
Map.Entry<String,JsonElement> entry = entrySet.iterator().next();
modelData = new ModelData(entry.getKey(),entry.getValue().getAsDouble());
}
}
return modelData;
}
}
и пробую парсить, я понимаю в десериализаторе надо поставить цикл и записывать в массив. Что то доделать не могу : `
Gson gson = new GsonBuilder()
.registerTypeAdapter(ModelData.class,new DeserializerCurrency())
.create();
ModelData modelData = gson.fromJson(rates.toJSONString(),ModelData.class);`
UPD
Я переделал десериализатор.
public class DeserializerCurrency implements JsonDeserializer<ModelData> {
@Override
public ModelData deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
ModelData modelData = null;
List<ModelData> ListModelData = new ArrayList<>();
if(json.isJsonObject()){
Set<Map.Entry<String,JsonElement>> entrySet = json.getAsJsonObject().entrySet();
if(entrySet.size() > 0){
Iterator<Map.Entry<String,JsonElement>> entries = entrySet.iterator();
while (entries.hasNext()){
Map.Entry<String,JsonElement> entry = entries.next();
ListModelData.add(new ModelData(entry.getKey(),entry.getValue().getAsDouble()));
}
}
}
return modelData;
}
}
Теперь в массиве всё что надо, но вернуть его не могу, так как в return один объект, а не массив. Для этого надо подключить другой интерфейс, типо JsonDeserializer> . Как быть? Класс такого типа я создать не могу, что на вход подать то?
Map<String, Double>Модель:
public class ModelData {
Map<String, Double> rates = new HashMap<>();
@Override
public String toString() {
return "ModelData{" +
"rates=" + rates +
'}';
}
}
Маин:
Gson gson = new Gson();
ModelData modelData = gson.fromJson(JSON2, ModelData.class);
Если вам не нужна Map, а нужна каждая валюта по отдельности, то это можно сделать 1000 и 1 различными способами.
Моя импровизация:
public class ModelData {
Map<String, Double> rates = new HashMap<>();
public List<Currency> convertToCurrency(){
return rates.entrySet().stream()
.map(m -> new Currency(m.getKey(), m.getValue()))
.collect(Collectors.toList());
}
public static class Currency{
String name;
double val;
public Currency(String name, double val) {
this.name = name;
this.val = val;
}
}
}
Теперь если в маин вызвать метод, получить список валют и вывести на экран получим:
Currency{name='AUD', val=1.5565}
Currency{name='BGN', val=1.9558}
Currency{name='BRL', val=3.8193}
Currency{name='CAD', val=1.4963}
...
Так же можно просто в ModelData определить метод, в который передавать имя валюты, а возвращать объект Currency. Либо напрямую с Map общаться...
Я с JSON знаком, но не могу объяснить в чем конкретно ваша ошибка и как вам надо сделать в идеале. Надеюсь попозже кто-то объяснит, я пока предложил вам рабочий вариант.
Т.к. автору нужны все данные, а не только валюты, нужна модель входящих данных:
class IncomeData {
// без конструкторов, toString и гет\сет для экономии места
String base;
LocalDate date;
List<ModelData> rates;
}
ModelData не изменилась (имя, значение).
Вся работа со строкой, во входящей строке лежит json из вопроса (полный).
public IncomeData deserialize(String json) throws JSONException {
//парсим строку в json
JSONObject jsonObject = new JSONObject(json);
//забираем base и date
String base = jsonObject.get("base").toString();
LocalDate date = LocalDate.parse(jsonObject.get("date").toString());
//заберем объект rates и пройдемся по нему итератором
//все валюты сложим в свои ModelData и все сложим в лист
JSONObject rates = jsonObject.getJSONObject("rates");
Iterator keys = rates.keys();
List<ModelData> ratesList = new ArrayList<>();
while (keys.hasNext()){
String key = (String)keys.next();
//Number потому, что по ключу "IDR" прилетает Integer
Number value = (Number) rates.get(key);
ratesList.add(new ModelData(key, value.doubleValue()));
}
//собираем IncomeData из полученных данных
IncomeData resultData = new IncomeData(base, date, ratesList);
return resultData;
}
В этот метод подаем строку json и на выходе получаем готовый объект
Не уверен правильно ли я Вас понял, но если вам приходит ответ в JSON формате и надо его распарсить, можно создать класс модель схожую на ответ и сделать следующее:
List<User> resList = new ArrayList<>();
if (TextUtils.isEmpty(strJSON)) { // <--- strJSON - Входящий JSON
return resList;
}
Gson gson = new Gson();
User[] users = gson.fromJson(strJSON, User[].class);
resList.addAll(Arrays.asList(users));
return resList;
Вместо User Ваш класс.
Современные инструменты для криптотрейдинга: как технологии помогают принимать решения
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости