You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:17:20