Fastjson/Jackson解析嵌套Map结构JSON报空指针的解决方法
问题根因
解析抛出空指针的核心原因是Java实体结构和JSON结构不匹配,叠加可能存在的JSON语法错误:
- 初始定义的实体类中,
Data类额外包装了mapKeyInfo属性,但实际JSON里data节点下直接是key1/key2这类动态key,不存在名为mapKeyInfo的子字段,框架无法匹配到对应属性,导致解析出的data对象或内部map为null,后续调用时触发空指针 - 给出的JSON示例存在语法错误:
data节点的闭合}后缺少分隔code节点的逗号,且子节点最后一个属性后多了冗余逗号,非法JSON本身就会导致解析失败
修正后的合法JSON结构参考:
{ "data": { "key1": { "t1": "text1", "t2": "text1" }, "key2": { "t1": "text1", "t2": "text1" } }, "code": 1 }
Fastjson 解析方案
推荐直接移除多余的Data包装层,实体结构完全对齐JSON:
- 实体类定义
@Getter @Setter public class JsonData { // data节点本身就是动态key的Map对象,value对应t1/t2结构 private Map<String, KeyInfo> data; private int code; @Getter @Setter public static class KeyInfo { private String t1; private String t2; } }
- 解析代码(Fastjson 1.2.83+ 版本直接解析即可,低版本可借助TypeReference处理泛型)
// 常规写法 JsonData jsonData = JSONObject.parseObject(response, JsonData.class); // 低版本泛型解析失败时用这个写法 JsonData jsonData = JSONObject.parseObject(response, new TypeReference<JsonData>() {});
如果一定要保留原有Data包装类,可在mapKeyInfo字段上增加注解,配置Fastjson将data节点下的所有属性反序列化到该字段,不过这种写法会增加不必要的结构复杂度,不推荐使用。
Jackson 解析方案
同样推荐对齐JSON结构的简化实体写法:
- 实体类定义和上述Fastjson所用实体完全一致,无需额外修改
- 解析代码
ObjectMapper objectMapper = new ObjectMapper(); // 可选配置:遇到JSON里有但实体没定义的字段时不抛错 objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); JsonData jsonData = objectMapper.readValue(response, JsonData.class);
如果遇到泛型擦除导致的解析异常,可通过JavaType显式指定类型:
JavaType targetType = objectMapper.getTypeFactory().constructType(JsonData.class); JsonData jsonData = objectMapper.readValue(response, targetType);
如果要保留原有Data包装层,可在Data类中增加@JsonAnySetter注解的方法,将所有动态key写入mapKeyInfo,同样不推荐这种冗余结构写法。
补充说明
之前尝试的Map<String, Map<String, String>>类型的data字段结构本身是符合JSON层级的,解析失败基本是两个原因:一是JSON字符串本身语法不合法,二是使用的框架版本过低存在泛型解析bug,升级到Fastjson 1.2.83+、Jackson 2.12+以上稳定版本即可正常解析。只是这种纯Map的写法需要手动通过字符串key取嵌套值,不如定义专门的KeyInfo类可读性强。
内容的提问来源于stack exchange,提问作者EthanAlef
相关产品推荐
相关产品推荐

