使用Gson解析JSON字符串失败,返回空对象并触发NPE问题排查
使用JDK 8、Gson V2.10.1(开发工具为IntelliJ及VS Code)解析JSON字符串时失败,返回的JSONObject为空对象,未解析出任何JSON元素。经调试发现,问题出在com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.java的public T read(JsonReader in) throws IOException方法中,执行BoundField field = boundFields.get(name)时触发了空指针异常(NPE)。
相关代码片段
JSON内容
{ "took" : 2, "hits" : { "total" : 19, "max_score" : 1.0, "hits" : [ { "_index" : "layouts-new", "_type" : "doc", "_id" : "a0b8707c-feb3-4867-966d-33c435c82141", "_score" : 1.0, ... } ] } }
自定义解析代码
Gson gson = new GsonBuilder().setLenient().create(); JSONObject jsonObject = gson.fromJson(json, JSONObject.class); ...
异常触发的源码片段
try { in.beginObject(); while (in.hasNext()) { String name = in.nextName(); BoundField field = boundFields.get(name); if (field == null || !field.deserialized) { in.skipValue(); } else { readField(accumulator, in, field); } } } catch (IllegalStateException e) { ... }
问题根源
你大概率是混用了不同JSON库的JSONObject类:Gson本身不支持直接反序列化到第三方JSON库的JSONObject(比如org.json.JSONObject),而是需要使用Gson原生的com.google.gson.JsonObject。
当Gson遇到一个没有内置TypeAdapter的类时,会尝试用反射机制创建适配器,但第三方JSONObject类内部通常用私有Map存储数据,Gson无法通过反射获取到可绑定的字段,导致boundFields为空甚至null,最终调用boundFields.get(name)时触发空指针异常,同时无法解析任何JSON元素,返回空对象。
解决方案
改用Gson原生
JsonObject
这是最直接的方案,Gson对自身的JsonObject有专门的TypeAdapter支持,能正确解析所有JSON元素:Gson gson = new GsonBuilder().setLenient().create(); JsonObject jsonObject = gson.fromJson(json, JsonObject.class);如果必须使用第三方
JSONObject
先解析为Gson原生JsonObject,再转换为目标JSONObject:Gson gson = new GsonBuilder().setLenient().create(); JsonObject gsonObj = gson.fromJson(json, JsonObject.class); JSONObject jsonObject = new JSONObject(gsonObj.toString());或者自定义一个TypeAdapter,让Gson直接支持第三方
JSONObject的反序列化。检查依赖与导入类
确认项目中没有引入冲突的JSON库,且代码中导入的JSONObject是预期的类(避免误导入Gson之外的JSONObject)。
内容的提问来源于stack exchange,提问作者Velusamy Velu

