net.sf.JSONExceptionMap中value字段为null,服务响应500

编程

6月2号凌晨系统生产发布,2号白天仓库作业时有仓库拣选单打印面单接口500,不是所有的拣选单掉接口都是500, 当时通过接口响应正产和响应500,逻辑梳理以及数据对比,最后发现是Map 对象里面有一个key 为null把map 对象转成JsonArray 导致的,经测试

JSONObject.fromObject
JSONArray.fromObject 

上面两个方法,入参是Map对象的时候如果value 里面存在null ,将格式化结果返回给前段都会响应500的

1. JsonArray.fromObject 过程,具体步骤如下图

 

下面是第7步中的执行步骤此处将null 替换成了JSONNull对象, JSONNull.getInstance() JSONNull对象

JSONNull 对象结构如下,它实现了JSON 接口这个很最重要,正是因为实现了这个接口,在后面的步骤中,都会进入到属于JSON 的分支里面

 

最后12步骤中1中判断

 

 

此时的object是一个JSONNull 对象,所以1中的前半段是trueisNull代码如图会走入红框中的逻辑所以是true 在进行!运算成了false 所以直接进入了分支2,返回的是一个JSONObject 对象重点啊,记住这个构造函数记住这个true,以及它是实现MAP 接口的

程序运行到这里是没有任何异常的,但我们知道SpringMVC 的一个响应流程不是到这里就结束的

2.MessageConverter 过程

整个调用链路如下图所示,具体不在分析了,感兴趣的同学可以自己分析一下,重点在消息转换的那一步 MessageConverter

具体分析最后两步

这个地方在找 value JSONObject对应的序列化类的时候,找到的还是MapSerializer 序列化类,为什么是MapSerializer  还记得JSONObject实现的接口么,其中有Map 接口

接着在执行 serializer.serialize(valueElem, gen, provider); 到下图时,valueElem JSONObject对象,查看对象里面的 isEmpty 源码

 

还记得那个构造函数么,那个true么,最后返回的JSONObject 对象isNullObject true ,所以在这里抛出了异常,真的是饶了一大圈,最终回到了这里

异常会被包装,往上层抛出

最终接口内部异常响应500

 

总结:

  1. 在遇到生产问题时,为了能快速的定位问题原因,如果可以动态修改日志级别,碰到这种情况,建议将日志级别调低,及时的抓获异常日志信息,定位问题原因,快速修复,让生产及时止血,这个日志级别设置在 WARN 是可以看到日志的
  2. 项目中的对JSON等第三方的工具包统一管控,统一配置例如设置全局的JsonConfig 类在使用 JSONObject,JSONArray的时候,都使用全局配置类
  3. 不要用Map 做为数据对象了,用Java 对象,不仅仅是Java 作为数据对象是可读性好,可以避免一些不知道的坑,例如上面的坑

以上是 net.sf.JSONExceptionMap中value字段为null,服务响应500 的全部内容, 来源链接: utcz.com/z/517157.html

回到顶部