ERROR com.fasterxml.jackson.databind.JsonMappingException

本文记录了一次使用PostMan测试时遇到的BUG,由于JSON数据中包含注释,导致后台抛出了com.fasterxml.jackson.databind.JsonMappingException。报错信息详细显示了问题所在。总结中强调了避免在JSON数据中添加注释,以免引发类似错误,并将BUG视为程序员成长的重要一课。

BUG描述

在用PostMan测试的时候,往后台传了json格式里带了注释的数据,后台报的这个错,记录一下。

{
   "name": "XXX",
//    这里加了注释
    
}
{
    "timestamp": "2021-08-19T10:25:52.524+00:00",
    "status": 400,
    "error": "Bad Request",
    "path": "/xxx/xxx"
}

报错信息

完整报错如下所示:

ERROR com.fasterxml.jackson.databind.JsonMappingException: Unexpected character ('/' (code 47)): maybe a (non-standard) commen t? (not recognized as one since Feature 'ALLOW_COMMENTS' not enabled for parser)

总结

往后台传参,json里不要加注释,很久之前好像遇见过这个错,在js文件里有些地方也加了注释,导致出错,时间有点久,一下没想起来,这次再次记录一下,加深印象,希望下次不要再犯。如果说书籍是人类进步的阶梯,那么BUG一定是程序员最好的老师!与诸君共勉。

<think> 我们正在解决的问题是:`com.fasterxml.jackson.databind.JsonMappingException: String length (20051112) exceeds the maximum length`。这个错误表明在反序列化过程中,某个字符串的长度(20051112)超过了Jackson库允许的最大长度限制。 根据Jackson的文档和常见问题,这个错误通常是由于在反序列化字符串时,字符串长度超过了`JsonParser.Feature.AUTO_CLOSE_SOURCE`中设置的最大长度限制。Jackson默认有一个字符串长度限制(默认值通常是`Integer.MAX_VALUE`,但可能在某些版本或配置中设置了一个较小的值)。然而,在这个错误中,字符串长度20051112(大约20MB)确实很大,可能超过了默认配置的限制。 解决方案通常有两种: 1. 增加字符串的最大允许长度。 2. 检查数据源,避免传输过大的字符串(如果业务上不需要)。 具体步骤如下: ### 方法1:配置ObjectMapper以允许更长的字符串 我们可以通过配置`JsonFactory`(或`ObjectMapper`)来设置`StreamReadConstraints`(在Jackson 2.15及以上版本)或使用`JsonParser.Feature`(在旧版本)来调整最大字符串长度。 **对于Jackson 2.15及以上版本**: 在Jackson 2.15中,引入了`StreamReadConstraints`来设置各种读取限制,包括字符串长度。 ```java // 创建StreamReadConstraints并设置最大字符串长度 StreamReadConstraints constraints = StreamReadConstraints.builder() .maxStringLength(30000000) // 设置为3000万,大于20051112 .build(); // 配置ObjectMapper ObjectMapper objectMapper = JsonMapper.builder() .streamReadConstraints(constraints) .build(); ``` **对于旧版本的Jackson(2.15之前)**: 在旧版本中,我们可以通过`JsonFactory`来设置`JsonParser.Feature`: ```java JsonFactory jsonFactory = new JsonFactory(); // 禁用字符串长度限制(或设置为一个很大的值) jsonFactory.disable(JsonFactory.Feature.INTERN_FIELD_NAMES); // 可选,但这不是针对长度 // 实际上,在2.15之前,Jackson并没有直接提供设置字符串最大长度的API。如果遇到此问题,可能需要升级到2.15+版本,或者考虑其他解决方案(如使用自定义反序列化器或检查数据源)。 // 另一种方法是使用系统属性(但这种方式在较新版本中可能已被废弃): // 在启动JVM时设置:-Dcom.fasterxml.jackson.core.StreamReadConstraints.maxStringLength=30000000 ``` 注意:在旧版本中,可能无法直接设置最大字符串长度。如果无法升级,可能需要考虑其他方法。 ### 方法2:检查数据源并优化 如果字符串确实非常大,考虑是否真的需要一次性传输这么大的字符串。可能可以通过分页、流式处理或改为传输文件等方式优化。 ### 方法3:自定义反序列化处理 如果上述方法不可行,可以考虑自定义反序列化器,在反序列化时处理大字符串。 ```java public class CustomStringDeserializer extends JsonDeserializer<String> { @Override public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { // 这里可以读取文本,并处理超长情况,但注意,默认情况下,读取超长字符串已经报错,所以这里可能无法直接解决。 // 除非在自定义反序列化器中,我们使用其他方式读取(比如分段读取),但通常不建议。 return p.getText(); } } ``` 然后注册这个自定义反序列化器: ```java SimpleModule module = new SimpleModule(); module.addDeserializer(String.class, new CustomStringDeserializer()); objectMapper.registerModule(module); ``` 但是,这种方法并不能绕过Jackson内部的长度限制,因为`p.getText()`仍然会触发长度检查。因此,最好的方法还是升级Jackson并配置`StreamReadConstraints`。 ### 总结 1. 升级Jackson到2.15+版本,并配置`StreamReadConstraints`增加最大字符串长度。 2. 如果无法升级,尝试寻找是否有替代的系统属性可以设置(但请注意,旧版本可能不支持)。 3. 优化数据,避免传输过大的字符串。 根据引用[5]中的示例,我们看到代码中使用了`JSonUtils`(可能是自定义的工具类)。如果这个工具类内部使用了`ObjectMapper`,那么我们需要修改其配置。例如: ```java // 假设JSonUtils中有一个获取ObjectMapper的方法 public class JSonUtils { private static final ObjectMapper mapper = new ObjectMapper(); // 修改配置 static { // 对于Jackson 2.15+ StreamReadConstraints constraints = StreamReadConstraints.builder() .maxStringLength(30000000) .build(); mapper.setStreamReadConstraints(constraints); } // ... 其他方法 } ``` 如果使用旧版本,可能需要寻找其他方式。 注意:在设置最大字符串长度时,要考虑到内存使用和潜在的安全风险(例如,防止恶意超长字符串导致内存耗尽)。 如果问题仍然存在,建议检查完整的堆栈跟踪,确认错误发生的具体位置,以便更有针对性地解决。 希望这些方法能帮助您解决问题。 §§相关问题§§ 1. 如何在Spring Boot中全局配置Jackson的`StreamReadConstraints`? 2. 除了增加字符串长度限制,还有哪些方法可以处理Jackson反序列化大字符串的问题? 3. 如何自定义Jackson的反序列化器来处理特定类型的超大字符串字段? </think> ### 解决 `com.fasterxml.jackson.databind.JsonMappingException: String length exceeds the maximum length` 的方法 此错误表明 Jackson 在反序列化 JSON 数据时,遇到了超过其默认长度限制的字符串(如示例中的 20,051,112 个字符)。以下是系统性的解决方法: --- ### **1. 调整 Jackson 的字符串长度限制(推荐)** Jackson 默认限制字符串长度(通常为 `Integer.MAX_VALUE`,约 2GB)。若需支持更长字符串,需显式配置 `StreamReadConstraints`: ```java // Spring Boot 配置示例(Jackson 2.15+) @Configuration public class JacksonConfig { @Bean public ObjectMapper objectMapper() { return JsonMapper.builder() .streamReadConstraints(StreamReadConstraints.builder() .maxStringLength(500_000_000) // 设置为 500MB .build()) .build(); } } ``` - **关键参数**:`maxStringLength` 根据需求调整(需大于实际字符串长度)。 - **旧版 Jackson**:可通过系统属性配置: ```bash -Dcom.fasterxml.jackson.core.StreamReadConstraints.maxStringLength=500000000 ``` --- ### **2. 优化 JSON 数据结构** 若字符串长度异常(如 2000 万字符),可能是设计问题: - **避免超大字符串**:拆分字段或使用分页传输(如改为传输文件 ID 或分段加载)。 - **压缩数据**:使用 `gzip` 压缩字符串,客户端解压(需协商传输编码)。 --- ### **3. 检查数据源** 验证输入数据的合理性: - **日志分析**:检查是否因数据错误导致异常值(如日志污染)。 - **数据截断**:在持久层(如数据库)添加长度校验: ```sql ALTER TABLE your_table MODIFY your_column VARCHAR(500); -- 限制长度 ``` --- ### **4. 替换反序列化方式(备选)** 若无法升级 Jackson 或调整配置: - **自定义反序列化器**:绕过长度检查(不推荐,有内存溢出风险): ```java public class CustomStringDeserializer extends JsonDeserializer<String> { @Override public String deserialize(JsonParser p, DeserializationContext ctx) throws IOException { return p.getText(); // 直接读取,忽略长度检查 } } ``` - **注册自定义反序列化器**: ```java SimpleModule module = new SimpleModule(); module.addDeserializer(String.class, new CustomStringDeserializer()); objectMapper.registerModule(module); ``` --- ### **原因分析** - 错误直接原因是 JSON 中某字段的字符串值超过 Jackson 的默认长度限制。 - 根本原因可能是: - 数据设计缺陷(如传输未压缩的二进制文件 Base64 字符串)。 - 日志/错误信息被误写入 JSON 字段[^1]。 - 数据库未校验字段长度。 --- ### **验证步骤** 1. 在报错位置添加调试日志,输出字段名和长度: ```java catch (JsonMappingException e) { log.error("Field causing error: {}", e.getPath().get(0).getFieldName()); } ``` 2. 使用 `curl` 或 Postman 模拟请求,验证字段内容。 > **注意**:盲目提高长度限制可能导致内存溢出(OOM),需结合业务评估合理性。若处理文件等二进制数据,建议改用 `byte[]` 或文件传输协议。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值