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
相关产品推荐
相关产品推荐

