如何用Gson/Retrofit处理含未知动态键的API响应POJO映射?
这种动态键的JSON结构确实有点棘手,不过Gson提供了几种简洁的解决方案,我来给你详细说说:
方法1:直接使用Map<Integer, 你的POJO类>
这是最直接的方案,因为Gson可以自动将JSON中的动态整数键映射为Map的键,对应的值则映射为你定义的内部POJO对象。
首先,先定义内部的POJO类(假设你需要解析的对象字段是name和value,你可以根据实际情况修改):
public class Item { private String name; private int value; // 生成构造函数、getter、setter和toString方法 public Item() {} public String getName() { return name; } public void setName(String name) { this.name = name; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } @Override public String toString() { return "Item{name='" + name + "', value=" + value + "}"; } }
然后用Gson解析JSON响应:
// 你的API返回的JSON字符串 String jsonResponse = "{ \"29593\": { \"name\": \"Item A\", \"value\": 100 }, \"29594\": { \"name\": \"Item B\", \"value\": 200 }, \"29600\": { \"name\": \"Item C\", \"value\": 300 } }"; Gson gson = new Gson(); // 使用TypeToken获取泛型Map的类型 Type itemMapType = new TypeToken<Map<Integer, Item>>(){}.getType(); Map<Integer, Item> itemMap = gson.fromJson(jsonResponse, itemMapType); // 遍历Map获取每个对象和对应的ID for (Map.Entry<Integer, Item> entry : itemMap.entrySet()) { int itemId = entry.getKey(); Item item = entry.getValue(); System.out.println("对象ID: " + itemId + ", 内容: " + item); }
这种方法适合只需要关联ID和对象的场景,代码简单,不需要额外的自定义逻辑。
方法2:自定义反序列化器,将ID整合到POJO中
如果你希望把动态的对象ID直接放到POJO对象里(比如给Item类加一个id字段),可以通过自定义JsonDeserializer来实现。
首先修改Item类,添加id字段:
public class Item { private int id; private String name; private int value; // 生成构造函数、getter、setter和toString方法 public Item() {} 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; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } @Override public String toString() { return "Item{id=" + id + ", name='" + name + "', value=" + value + "}"; } }
然后编写自定义的反序列化器:
import com.google.gson.*; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; import java.util.Map; public class ItemListDeserializer implements JsonDeserializer<List<Item>> { @Override public List<Item> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { List<Item> itemList = new ArrayList<>(); JsonObject jsonObject = json.getAsJsonObject(); // 遍历JSON中的每个键值对 for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) { // 将字符串键转为整数ID int itemId = Integer.parseInt(entry.getKey()); // 解析内部的JSON对象为Item实例 Item item = context.deserialize(entry.getValue(), Item.class); // 设置ID item.setId(itemId); itemList.add(item); } return itemList; } }
最后注册并使用这个反序列化器:
String jsonResponse = "{ \"29593\": { \"name\": \"Item A\", \"value\": 100 }, \"29594\": { \"name\": \"Item B\", \"value\": 200 }, \"29600\": { \"name\": \"Item C\", \"value\": 300 } }"; Gson gson = new GsonBuilder() .registerTypeAdapter(new TypeToken<List<Item>>(){}.getType(), new ItemListDeserializer()) .create(); List<Item> itemList = gson.fromJson(jsonResponse, new TypeToken<List<Item>>(){}.getType()); // 输出结果 for (Item item : itemList) { System.out.println(item); }
这种方法适合你需要把ID和对象数据放在一起统一处理的场景,后续使用起来更方便。
内容的提问来源于stack exchange,提问作者Angelina
相关产品推荐
相关产品推荐

