首页 > 解决方案 > 如何将键值映射反序列化为列表

问题描述

我想在我的 Spring Boot 应用程序中使用此处描述的加密股票数据。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;
}

知道如何做到这一点吗?

标签: javaspring-bootgson

解决方案


因为对此的响应API是动态的并且取决于参数,所以最好的选择是在反序列化端使用动态结构。最好的选择是Map。作为键,您可以使用Stringenum: 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-sSymbol你需要实现自定义反序列化器。例如,看看这个问题:Parsing JSON Array to Java List Using Gson


推荐阅读