Как десериализовать карту ключ-значение в список - PullRequest
1 голос
/ 16 апреля 2019

Я хочу работать с криптографическими данными, описанными здесь в моем приложении весенней загрузки. RESTTemplate использует Gson для десериализации. Данные ответа выглядят так:

{
  "IOST": {
    "EUR": 0.01147,
    "USD": 0.01296
  },
  "XRP": {
    "EUR": 0.2837,
    "USD": 0.3208
  },
  ...
}

Я уже писал собственный десериализатор. Проблема в том, что это происходит как один объект с парами ключ-значение, вставленными в массив. Результатом должен быть список следующих объектов:

public class Symbol {
    private Long id; // not relevant during conversion
    private Date timestamp; // not relevant during conversion
    private String symbol;
    private Double eurPrice;
    private Double usdPrice;
}

Есть идеи, как этого добиться?

Ответы [ 3 ]

1 голос
/ 16 апреля 2019

Поскольку ответ от этого API является динамическим и зависит от параметров, лучший выбор - использовать динамическую структуру на стороне десериализации. Лучший выбор - Map. В качестве ключей вы можете использовать String или enum: Currency, Crypto. После десериализации вы можете конвертировать Map в необходимый POJO класс. Простой пример:

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class GsonTest {

    public static void main(String[] args) {
        String json = "{\"IOST\": {"
            + "    \"EUR\": 0.01147,"
            + "    \"USD\": 0.01296"
            + "  },"
            + "  \"XRP\": {"
            + "    \"EUR\": 0.2837,"
            + "    \"USD\": 0.3208"
            + "}}";

        Gson gson = new GsonBuilder().create();
        Type type = new TypeToken<Map<String, Map<Currency, BigDecimal>>>() {
        }.getType();

        Map<String, Map<Currency, BigDecimal>> response = gson.fromJson(json, type);

        List<Symbol> symbols = response.entrySet()
            .stream()
            .map(e -> {
                Symbol symbol = new Symbol();
                symbol.setSymbol(e.getKey());
                symbol.setEurPrice(
                    e.getValue().getOrDefault(Currency.EUR, BigDecimal.ZERO).doubleValue());
                symbol.setUsdPrice(
                    e.getValue().getOrDefault(Currency.USD, BigDecimal.ZERO).doubleValue());

                return symbol;
            }).collect(Collectors.toList());

        System.out.println(symbols);
    }

    enum Currency {
        EUR,
        USD
    }
}

Над примером печатает:

[Symbol{id=null, timestamp=null, symbol='IOST', eurPrice=0.01147, usdPrice=0.01296}, Symbol{id=null, timestamp=null, symbol='XRP', eurPrice=0.2837, usdPrice=0.3208}]

Если вы хотите напрямую создать List из Symbol -s, вам нужно реализовать собственный десериализатор. Например, взгляните на этот вопрос: Анализ массива JSON в списке Java с помощью Gson

0 голосов
/ 16 апреля 2019

Hareshs anweser не подошел на 100%, но он помог мне разобраться:

var url = "...";
var entries = new ArrayList<Symbol>();
var timestamp = Timestamp.from(Instant.now());
Symbol symbol;

ResponseEntity<JsonObject> response = restTemplate.getForEntity(url, JsonObject.class);

for (Map.Entry<String, JsonElement> entry : response.getBody().entrySet()) {
    symbol = new Symbol();
    symbol.setSymbol(entry.getKey());
    symbol.setEurPrice(entry.getValue().getAsJsonObject().get("EUR").getAsDouble());
    symbol.setUsdPrice(entry.getValue().getAsJsonObject().get("USD").getAsDouble());
    symbol.setTimestamp(timestamp);

    entries.add(symbol);
}

Вот и все.Однако, если кто-нибудь найдет способ сделать это полностью в десериализаторе Gson, я бы очень хотел это услышать!

0 голосов
/ 16 апреля 2019

Вы должны сделать класс, как показано ниже

public class Symbol  {

    private double EUR;
    private double USD;

    public double getEUR() {
        return EUR;
    }

    public void setEUR(double EUR) {
        this.EUR = EUR;
    }

    public double getUSD() {
        return USD;
    }

    public void setUSD(double USD) {
        this.USD = USD;
    }
}

Вверху - модель, а ниже - разбор

try {
        HashMap<String, Symbol> multiMap = new HashMap<String, Symbol>();
        JSONObject mJsonObject = new JSONObject(mResponse);
        Iterator<String> iter = mJsonObject.keys();
        while (iter.hasNext()) {
            String key = iter.next();
            try {
                Symbol msymbol = new Symbol();
                msymbol.setEUR(mJsonObject.getJSONObject(key).getDouble("EUR"));
                msymbol.setEUR(mJsonObject.getJSONObject(key).getDouble("USD"));
                multiMap.put(key, msymbol);

            } catch (JSONException e) {
                // Something went wrong!
            }
        }



    }catch (Exception e){
        e.printStackTrace();
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...