为何启用ESCAPE_NON_ASCII才能让Receiver解析含µ的JSON?
问题原因分析及解决思路
核心认知纠正:µ的UTF-8编码并非单字节0xb5
首先要明确:µ的标准UTF-8编码是双字节0xC2 0xB5,单字节0xB5是ISO-8859-1(Latin-1)编码下的µ值。Jackson默认生成合法UTF-8的说法没错,但Receiver抛出的Invalid UTF-8 start byte 0xb5异常,说明它接收到的字节流里出现了单字节0xB5,而非标准的UTF-8双字节序列。
问题根源:编码链路的两处不匹配
Sender端的编码转换漏洞
Jackson将POJO序列化为String时,确实是按UTF-8生成字符,但如果后续你把这个String转成发送字节流时,错误使用了ISO-8859-1这类单字节编码,就会把原本UTF-8的双字节0xC2 0xB5拆成两个独立字符,其中0xB5被单独发送,导致Receiver收到非法的UTF-8起始字节。Receiver端自定义反序列化器的逻辑缺陷
Receiver的JsonToStringValueDeserializer是为兼容Sender2的base64格式设计的,这个自定义逻辑大概率没正确处理UTF-8多字节字符:
- 比如直接按单字节读取输入流,把UTF-8的多字节序列拆成单个字节处理;
- 或者在字节转字符串的步骤中,错误指定了单字节编码(如ISO-8859-1),转成UTF-8时触发编码错乱,抛出无效字节异常。
为何开启ESCAPE_NON_ASCII就能正常解析?
开启该配置后,Jackson会把所有非ASCII字符(包括µ)转义成Unicode转义序列\u00b5,这个序列全是ASCII字符。无论Sender用什么编码发送,Receiver读取时都不会出现字节解析错误,因此能正常处理。
修复建议
- Sender端:确保String转发送字节流时严格使用UTF-8编码,比如调用
string.getBytes(StandardCharsets.UTF_8),而非依赖平台默认编码。 - Receiver端:检查
JsonToStringValueDeserializer的逻辑,强制在字节流转字符串时使用UTF-8编码,同时调整处理逻辑,避免单字节解析破坏UTF-8多字节序列。
内容的提问来源于stack exchange,提问作者shibel
相关产品推荐
相关产品推荐

