Jackson反序列化CoinMarketCap API含伪对象数组的JSON字符串问题
嘿,我之前也踩过CoinMarketCap这个v2 API的坑!这个data字段确实有点反直觉——明明看起来是一组币种数据,却做成了以币种ID为键的命名键值对,而非标准数组,给POJO映射添了不少麻烦。下面给你几个实用的解决办法,不管你用Jackson还是Gson都能轻松搞定:
方法一:用Jackson的
Map<Integer, YourCoinPOJO>直接接收 这是最直接的方案,因为API返回的data本质就是一个键为数字ID、值为币种对象的映射。
首先定义你的币种实体类,对应单个币种的字段:
public class Coin { private int id; private String name; private String symbol; private double price_usd; // 按需添加其他字段,记得加上getter和setter }
然后定义外层的响应类,用Map来接收data字段:
public class CmcTickerResponse { private Map<Integer, Coin> data; private Status status; // 可选,如果你需要处理API返回的状态信息 // getter和setter } // 可选的Status类,对应API返回的status字段 public class Status { private String timestamp; private int error_code; // 其他状态字段 }
解析的时候就用常规的Jackson ObjectMapper:
ObjectMapper mapper = new ObjectMapper(); CmcTickerResponse response = mapper.readValue(apiResponseString, CmcTickerResponse.class); // 要是想转成List方便遍历,直接取Map的values就行 List<Coin> coinList = new ArrayList<>(response.getData().values());
方法二:用Gson处理同样的Map结构
如果你习惯用Gson,思路和上面一致,只是解析方式略有不同。
同样先定义好Coin和CmcTickerResponse类,然后解析时借助TypeToken:
Gson gson = new Gson(); Type responseType = new TypeToken<CmcTickerResponse>() {}.getType(); CmcTickerResponse response = gson.fromJson(apiResponseString, responseType); List<Coin> coinList = new ArrayList<>(response.getData().values());
方法三:自定义反序列化器,直接转成List
如果不想用Map,希望data字段直接映射成List,可以自定义一个反序列化器来处理。
以Jackson为例,先写反序列化器:
public class CoinListDeserializer extends JsonDeserializer<List<Coin>> { @Override public List<Coin> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { JsonNode dataNode = p.getCodec().readTree(p); List<Coin> coinList = new ArrayList<>(); // 遍历所有子节点,转成Coin对象 for (JsonNode coinNode : dataNode) { Coin coin = p.getCodec().treeToValue(coinNode, Coin.class); coinList.add(coin); } return coinList; } }
然后在响应类的data字段上加上注解指定使用这个反序列化器:
public class CmcTickerResponse { @JsonDeserialize(using = CoinListDeserializer.class) private List<Coin> data; private Status status; // getter和setter }
这样解析后,response.getData()直接就是List<Coin>,不用再手动转换Map的值啦!
小提示
记得确保你的POJO字段名和API返回的JSON字段名一致,如果字段名不一样(比如你把price_usd改成priceUsd),要加上@JsonProperty("price_usd")(Jackson)或者@SerializedName("price_usd")(Gson)来做字段映射哦!
内容的提问来源于stack exchange,提问作者user1531605
相关产品推荐
相关产品推荐

