Spring Jackson反序列化报MismatchedInputException无字符串构造器错误
问题根因
这个报错和实体类构造方法、Lombok注解没有关系,核心原因是传入readValue方法的字符串不是标准的JSON对象结构,是被二次序列化后包裹成字符串值的转义JSON。
从异常信息可以看到,Jackson识别到传入的内容是一个String类型的值(开头就是被双引号包裹的JSON内容),它会尝试找可以接收String参数的构造方法/工厂方法把这个字符串直接转为BenefitRequest对象,找不到就抛出了当前异常。
出现这个问题的典型场景是数据入库时做了双重序列化:原本已经是JSON格式的字符串,在存储时又被调用一次JSON序列化操作,导致最终存到库里的内容最外层多了一对双引号,内部的双引号都被转义成\"格式,取出来时就不是可以直接解析为对象的纯JSON结构。
排查方法
- 直接打印
item.getRequestString()的原始内容,检查第一个字符如果是"而不是{,即可确认是双重序列化问题。 - 可以用测试代码验证判断:如果第一层解析为String成功,再拿解析结果转实体类不报错,就完全符合问题特征。
解决方案
临时兼容方案
如果暂时无法调整数据写入逻辑,可以通过两层反序列化兼容现有数据:
ObjectMapper objectMapper = new ObjectMapper(); // 第一步:解析外层包裹的字符串,拿到真实的JSON对象内容 String actualJson = objectMapper.readValue(item.getRequestString(), String.class); // 第二步:将真实JSON解析为目标实体 BenefitRequest beneRequest = objectMapper.readValue(actualJson, BenefitRequest.class);
根因修复方案
排查数据写入数据库的逻辑,移除多余的一次序列化操作:
- 如果使用ORM框架(MyBatis、JPA等)的JSON类型处理器,检查是否存在手动将实体转JSON字符串后,又被框架自动序列化一次的问题,保留其中一种序列化逻辑即可。
- 如果写入时本身已经拿到了标准JSON字符串,不要额外调用
objectMapper.writeValueAsString()对字符串再做一次序列化,直接存储原始JSON内容即可。
补充说明
你贴出的标准JSON示例和实体类结构是完全匹配的,之前尝试添加@AllArgsConstructor、@Jacksonized注解是用于解决Lombok @Builder和Jackson协作时的构造器识别问题,和本次报错场景不匹配,所以无法解决问题。
异常日志里截断显示的providerid小写问题是日志截断导致的显示异常,不是本次报错的触发原因。
内容的提问来源于stack exchange,提问作者Tom Henricksen
相关产品推荐
相关产品推荐

