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

Gson反序列化时能否定位引发异常的目标字段?

解决Gson反序列化时定位无效字段的问题

默认情况下Gson抛出的NumberFormatException确实不会附带具体的字段信息,不过我们可以通过自定义TypeAdapterFactory来扩展Gson的解析逻辑,在异常中添加上当前解析的字段路径,这样就能精准定位到出问题的字段了。

实现思路

利用Gson的JsonReader.getPath()方法获取当前正在解析的JSON字段路径,在捕获解析异常时,将字段信息注入到异常消息中,重新抛出。

代码实现

首先创建一个通用的数值类型TypeAdapterFactory(支持Integer、Long、Double等所有Number子类):

import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;

public class FieldAwareNumberTypeAdapterFactory implements TypeAdapterFactory {
    @SuppressWarnings("unchecked")
    @Override
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
        // 只处理Number的子类类型
        if (!Number.class.isAssignableFrom(type.getRawType())) {
            return null;
        }
        
        TypeAdapter<T> delegateAdapter = (TypeAdapter<T>) gson.getDelegateAdapter(this, type);
        return new TypeAdapter<T>() {
            @Override
            public void write(JsonWriter out, T value) throws IOException {
                delegateAdapter.write(out, value);
            }

            @Override
            public T read(JsonReader in) throws IOException {
                try {
                    return delegateAdapter.read(in);
                } catch (NumberFormatException e) {
                    // 获取当前字段的完整路径(嵌套对象会返回类似"employee.department.id"的层级路径)
                    String fieldPath = in.getPath();
                    throw new NumberFormatException(String.format("Invalid value for field '%s': %s", fieldPath, e.getMessage()));
                }
            }
        };
    }
}

然后在创建Gson实例时注册这个工厂类:

Gson gson = new GsonBuilder()
        .registerTypeAdapterFactory(new FieldAwareNumberTypeAdapterFactory())
        .create();

效果测试

用你提供的测试代码运行:

try {
    String data = "{\"name\":\"Alan\",\"age\":\"twenty-eight\"}";
    Employee employee = gson.fromJson(data, Employee.class);
} catch (Exception e) {
    logger.warn(e);
}

此时抛出的异常会变成:

java.lang.NumberFormatException: Invalid value for field 'age': For input string: "twenty-eight"

这样就能直接看到是age字段的数值解析失败了,如果是嵌套对象的情况(比如{"employee":{"department":{"id":"not-a-number"}}}),异常会显示employee.department.id,精准定位到深层字段。

扩展说明

如果需要处理其他类型的解析异常(比如日期格式错误),可以用同样的思路,针对对应的类型编写TypeAdapterFactory,在捕获异常时注入字段路径信息即可。

内容的提问来源于stack exchange,提问作者Alanight

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:24:13