如何用Retrofit解析含未知Key的JSON并转为ArrayList?
解决Retrofit解析动态Key JSON并存入ArrayList的问题
我来帮你搞定这个动态Key JSON解析的难题——之前尝试的方案没出结果,应该是没抓准Retrofit配合Gson处理动态字段的正确方式。下面给你两种直接可用的方案,覆盖大多数常见场景:
方案一:直接用Map接收动态Key,再转成ArrayList
这是最简洁的方法,适合JSON外层全是动态Key的情况(比如下面这种结构):
{
"random_key_1": {"id": 1, "name": "苹果"},
"random_key_2": {"id": 2, "name": "香蕉"},
"random_key_3": {"id": 3, "name": "橙子"}
}
步骤1:定义数据模型类
先写对应每个动态Key内部数据的POJO,比如Goods.java:
public class Goods { private int id; private String name; // 务必添加Getter和Setter方法,或者用Lombok的@Data注解简化 public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
步骤2:定义Retrofit接口
把接口的返回类型改成Call<Map<String, Goods>>,让Gson自动把动态Key解析成Map的键:
public interface GoodsApi { @GET("goods/list") // 替换成你的实际接口路径 Call<Map<String, Goods>> getDynamicGoods(); }
步骤3:发起请求并转成ArrayList
在回调里把Map的values()直接转成ArrayList即可:
GoodsApi goodsApi = retrofit.create(GoodsApi.class); goodsApi.getDynamicGoods().enqueue(new Callback<Map<String, Goods>>() { @Override public void onResponse(Call<Map<String, Goods>> call, Response<Map<String, Goods>> response) { if (response.isSuccessful() && response.body() != null) { // 核心操作:把Map的值集合转成ArrayList ArrayList<Goods> goodsList = new ArrayList<>(response.body().values()); // 现在goodsList就是你要的列表,直接用它做后续业务逻辑就行 } else { // 处理请求失败(比如状态码非200) Log.e("Retrofit", "请求失败:" + response.message()); } } @Override public void onFailure(Call<Map<String, Goods>> call, Throwable t) { // 处理网络错误 Log.e("Retrofit", "网络异常:" + t.getMessage()); } });
方案二:外层有固定Key,内部嵌套动态Key的情况
如果你的JSON是外层有固定字段,里面才是动态Key(比如下面这种),就需要在外层POJO里用Map接收动态部分:
{
"code": 200,
"msg": "请求成功",
"data": {
"random_key_1": {"id": 1},
"random_key_2": {"id": 2}
}
}
步骤1:定义外层响应类
public class ApiResponse { private int code; private String msg; private Map<String, Goods> data; // 用Map接收动态Key的部分 // Getter和Setter方法 public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public Map<String, Goods> getData() { return data; } public void setData(Map<String, Goods> data) { this.data = data; } }
步骤2:修改Retrofit接口
返回类型改成Call<ApiResponse>:
public interface GoodsApi { @GET("goods/list") Call<ApiResponse> getDynamicGoods(); }
步骤3:解析并转成ArrayList
goodsApi.getDynamicGoods().enqueue(new Callback<ApiResponse>() { @Override public void onResponse(Call<ApiResponse> call, Response<ApiResponse> response) { if (response.isSuccessful() && response.body() != null) { ApiResponse apiResponse = response.body(); if (apiResponse.getCode() == 200 && apiResponse.getData() != null) { ArrayList<Goods> goodsList = new ArrayList<>(apiResponse.getData().values()); // 拿到列表做后续操作 } } } @Override public void onFailure(Call<ApiResponse> call, Throwable t) { // 处理网络错误 } });
关键提醒
确保你的Retrofit实例已经添加了Gson转换器,否则无法自动解析JSON:
Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://your-base-url.com/") // 替换成你的基础URL .addConverterFactory(GsonConverterFactory.create()) .build();
如果这两种方案还是不行,你可以把具体的JSON结构贴出来,我再帮你调整适配方案~
内容的提问来源于stack exchange,提问作者Siddhesh Pawar
相关产品推荐
相关产品推荐

