使用Gson读取数据时如何避免整数被转换为双精度浮点数?
解决Gson反序列化时整数转为Double的问题
这个问题在使用Gson处理无明确类型的Map时特别常见——因为JSON本身不区分整数和浮点数类型,Gson默认会把所有JSON数字都解析为Double,哪怕它原本是整数。下面给你两种可行的解决办法:
方法一:自定义Number类型适配器(推荐)
通过编写一个TypeAdapter来拦截数字的解析逻辑,根据数字的实际格式判断是转为整数类型还是保留浮点型:
import com.google.gson.TypeAdapter; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonWriter; import java.io.IOException; public class NumberTypeAdapter extends TypeAdapter<Number> { @Override public void write(JsonWriter out, Number value) throws IOException { out.value(value); } @Override public Number read(JsonReader in) throws IOException { JsonToken token = in.peek(); if (token == JsonToken.NUMBER) { String numStr = in.nextString(); // 判断是否为整数格式 if (numStr.contains(".") || numStr.toLowerCase().contains("e")) { return Double.parseDouble(numStr); } else { // 根据数字长度选择Integer或Long,避免溢出 if (numStr.length() <= 10) { return Integer.parseInt(numStr); } else { return Long.parseLong(numStr); } } } else if (token == JsonToken.NULL) { in.nextNull(); return null; } else { throw new IllegalArgumentException("Expected NUMBER or NULL but got: " + token); } } }
然后创建Gson实例时注册这个适配器:
Gson gson = new GsonBuilder() .registerTypeAdapter(Number.class, new NumberTypeAdapter()) .create(); // 现在反序列化就会保留整数类型了 Type type = new TypeToken<Map<String, Map<String, Object>>>() {}.getType(); Map<String, Map<String, Object>> myMap = gson.fromJson(dataFromCache, type);
方法二:使用JsonElement手动解析(适合简单场景)
如果你的数据结构不复杂,也可以先把JSON解析为JsonElement,再手动遍历转换数字类型:
JsonElement jsonElement = JsonParser.parseString(dataFromCache); Map<String, Map<String, Object>> myMap = new HashMap<>(); // 遍历外层Map for (Map.Entry<String, JsonElement> outerEntry : jsonElement.getAsJsonObject().entrySet()) { Map<String, Object> innerMap = new HashMap<>(); // 遍历内层Map for (Map.Entry<String, JsonElement> innerEntry : outerEntry.getValue().getAsJsonObject().entrySet()) { JsonElement value = innerEntry.getValue(); if (value.isJsonPrimitive()) { JsonPrimitive primitive = value.getAsJsonPrimitive(); if (primitive.isNumber()) { // 判断是否为整数 Number num = primitive.getAsNumber(); if (num instanceof Double && num.doubleValue() == num.longValue()) { innerMap.put(innerEntry.getKey(), num.longValue()); } else { innerMap.put(innerEntry.getKey(), num); } } else { innerMap.put(innerEntry.getKey(), primitive.getAsString()); } } else { // 处理非基本类型(如嵌套对象、数组),这里按需扩展 innerMap.put(innerEntry.getKey(), value); } } myMap.put(outerEntry.getKey(), innerMap); }
这种方法更灵活但代码量更大,适合只需要处理特定结构的场景。
内容的提问来源于stack exchange,提问作者learner
相关产品推荐
相关产品推荐

