Gson序列化Int键MutableMap后反序列化取值返回null问题排查
问题解答
1. JSON中能否存储Integer类型的Map键?
JSON规范明确要求所有键必须是字符串类型,所以无论你原Map的键是Integer还是其他数值类型,序列化成JSON后都会被自动转为字符串存储。但不需要必须改用String作为原Map的键,反序列化时可以通过配置让Gson把JSON中的字符串键转回Integer类型。
2. 你的序列化/反序列化写法问题
出现键被解析为String的核心原因,大概率是反序列化时没有指定Map的具体泛型类型,导致Gson因泛型擦除默认将键解析为String。
比如错误写法:
// 错误:直接用Map.class,泛型信息丢失,Gson默认解析为Map<String, ...> Map map = gson.fromJson(jsonString, Map.class);
正确写法需要用TypeToken明确指定嵌套Map的泛型结构,避免泛型擦除:
// 序列化 MutableMap<Integer, MutableMap<Integer, MutableMap<Integer, Time>>> dataMap = ...; Gson gson = new Gson(); String json = gson.toJson(dataMap); getSharedPreferences("your_sp_name", MODE_PRIVATE) .edit() .putString("saved_data", json) .apply(); // 反序列化 String savedJson = getSharedPreferences("your_sp_name", MODE_PRIVATE) .getString("saved_data", ""); // 用TypeToken指定完整的泛型类型 Type dataType = new TypeToken<MutableMap<Integer, MutableMap<Integer, MutableMap<Integer, Time>>>>() {}.getType(); MutableMap<Integer, MutableMap<Integer, MutableMap<Integer, Time>>> restoredMap = gson.fromJson(savedJson, dataType);
3. 特殊情况的处理
如果默认Gson解析仍有问题(比如部分字符串键无法转为Integer),可以自定义TypeAdapter来强制将JSON字符串键转为Integer:
public class IntegerKeyMapTypeAdapter extends TypeAdapter<Map<Integer, Object>> { private final Gson gson = new Gson(); @Override public void write(JsonWriter out, Map<Integer, Object> value) throws IOException { // 序列化时直接按正常逻辑处理,Gson会自动转Integer键为字符串 gson.toJson(value, Map.class, out); } @Override public Map<Integer, Object> read(JsonReader in) throws IOException { Map<String, Object> stringKeyMap = gson.fromJson(in, new TypeToken<Map<String, Object>>() {}.getType()); Map<Integer, Object> intKeyMap = new HashMap<>(); for (Map.Entry<String, Object> entry : stringKeyMap.entrySet()) { try { Integer key = Integer.parseInt(entry.getKey()); // 递归处理嵌套的Map if (entry.getValue() instanceof Map) { entry.setValue(read(gson.newJsonReader(new StringReader(gson.toJson(entry.getValue()))))); } intKeyMap.put(key, entry.getValue()); } catch (NumberFormatException e) { // 处理无法转为Integer的键,可根据需求忽略或抛出异常 e.printStackTrace(); } } return intKeyMap; } }
使用时需要在GsonBuilder中注册这个Adapter:
Gson gson = new GsonBuilder() .registerTypeAdapter(new TypeToken<Map<Integer, Object>>() {}.getType(), new IntegerKeyMapTypeAdapter()) .create();
内容的提问来源于stack exchange,提问作者Layer891203
相关产品推荐
相关产品推荐

