背景:
在今天工作时,临时收到生产问题,检查发现是在本服务Feign远程调用其他服务时方法时发生的,具体报错详情,及原因和解决方法均记录在下方。
报错详情:
feign.codec.DecodeException: Error while extracting response for type [java.util.List<Object>] and content type [application/json]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize instance of `java.util.ArrayList<Object>` out of START_OBJECT token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.util.ArrayList<Object>` out of START_OBJECT token
at [Source: (PushbackInputStream); line: 1, column: 1]
报错原因及解决方法:
原因:调用方接收数据的类型和服务端传回的数据类型不一致。
1、经过检查代码,发现两边所用的对象数据类型完全一致,甚至使用的类是公共jar下的同一个类,很奇怪,那为什么会发生这样的转换异常呢?
2、拉取生产代码,在测试库进行测试,发现完全正常,无法复现问题,那究竟是怎么造成的,难道是环境不一致造成的?
3、由于生产环境不能操作调试,测试环境无法复现,问题开始难办了,这时开始在网上搜索是否有同样的问题,发现大多这样异常均是数据类型不一致导致的,开始根据如下问题一一排查:
-
返回的 JSON 字符串与预期的 Java 类型不匹配。例如,JSON 中的某个字段为字符串类型,但在 Java 类型中却定义为数字类型。
-
返回的 JSON 字符串属性名与 Java 类型中定义的属性名不匹配。在这种情况下,Feign 无法将 JSON 字符串正确地转换为 Java 对象。
-
Feign 默认使用 Jackson 库进行 JSON 反序列化,如果返回的 JSON 字符串格式不符合标准,就会出现反序列化错误。例如,JSON 字符串中包含注释、单引号或未使用双引号引起来的字符串等。
-
可能是服务消费方(A服务)和服务提供方(B服务)使用的 JSON 库版本不一致,导致反序列化失败。可以尝试使用相同版本的 JSON 库,或者在 Feign 客户端中指定使用某个特定版本的 JSON 库。
4、在检查了上述问题后均没解决,这时突然灵感乍现,JSON parse error: Cannot deserialize instance of `java.util.ArrayList<Object>` out of START_OBJECT token,这段异常提示,不能由对象转换为List,是否数据问题或者代码逻辑使被调用方返回的异常格式的对象,这时联系有生产环境查询权限的同事进行确认,发现确实存在数据问题导致被调用服务内抛出了异常,返回了异常对象最终出现JSON parse error。
到此问题已解决,处理了被调用方问题后(无法更改被调用方时,本服务应该try-catch,将可能出现的异常自定义处理),一切正常。