JSON字符串控制字符未转义引发Jackson解码错误,求解决方法
解决JSON解析时控制字符未转义的Jackson错误
错误原因
你遇到的JsonMappingException是因为JSON规范(RFC 8259)明确要求:字符串中的ASCII控制字符(0x00到0x1F,除了\t、\n、\r、\f、\b这几个预定义转义符对应的字符)必须被转义为\uXXXX的形式。Jackson默认严格遵循这个规范,所以遇到未转义的\u001F这类控制字符时会直接报错。
解决方案
根据你的场景不同,这里提供三种可行的解决思路:
1. 生成JSON时自动转义控制字符(推荐)
如果是你自己负责生成JSON字符串,最规范的做法是在序列化阶段就处理控制字符,确保输出完全符合JSON标准。可以通过Jackson的自定义字符转义规则实现:
首先实现一个自定义的CharacterEscapes类,指定需要转义的控制字符:
import com.fasterxml.jackson.core.SerializableString; import com.fasterxml.jackson.core.io.CharacterEscapes; public class ControlCharacterEscapes extends CharacterEscapes { private final int[] escapeCodes; public ControlCharacterEscapes() { // 先继承JSON标准的默认转义规则 escapeCodes = standardEscapesForJSON(); // 对所有ASCII控制字符(0-31)启用标准转义 for (int i = 0; i < 32; i++) { escapeCodes[i] = CharacterEscapes.ESCAPE_STANDARD; } // 保留JSON允许的控制字符不转义 escapeCodes['\t'] = CharacterEscapes.ESCAPE_NONE; // 制表符 escapeCodes['\n'] = CharacterEscapes.ESCAPE_NONE; // 换行符 escapeCodes['\r'] = CharacterEscapes.ESCAPE_NONE; // 回车符 escapeCodes['\f'] = CharacterEscapes.ESCAPE_NONE; // 换页符 escapeCodes['\b'] = CharacterEscapes.ESCAPE_NONE; // 退格符 } @Override public int[] getEscapeCodesForAscii() { return escapeCodes; } @Override public SerializableString getEscapeSequence(int ch) { // 使用Jackson默认的转义序列(比如\u001F) return null; } }
然后在ObjectMapper中配置这个转义规则:
import com.fasterxml.jackson.databind.ObjectMapper; ObjectMapper mapper = new ObjectMapper(); mapper.getFactory().setCharacterEscapes(new ControlCharacterEscapes()); // 序列化对象时,控制字符会自动被转义为合法格式 String validJson = mapper.writeValueAsString(yourObject);
2. 预处理外部JSON字符串(适合接收脏数据)
如果是拿到了第三方提供的不符合规范的JSON字符串,可以先预处理,把未转义的控制字符替换成合法的转义序列:
写一个工具方法来清理字符串:
public static String sanitizeJson(String rawJson) { StringBuilder sanitized = new StringBuilder(rawJson.length()); for (char c : rawJson.toCharArray()) { // 只转义JSON规范不允许的控制字符 if (c < 32 && c != '\t' && c != '\n' && c != '\r' && c != '\f' && c != '\b') { // 转义为\uXXXX格式 sanitized.append(String.format("\\u%04x", (int) c)); } else { sanitized.append(c); } } return sanitized.toString(); }
然后先处理再解析:
String rawJson = "{ \"key\": \"abc No.\u001F\u001F...\" }"; String cleanedJson = sanitizeJson(rawJson); YourTargetClass result = mapper.readValue(cleanedJson, YourTargetClass.class);
3. 放宽Jackson的解析规则(不推荐)
如果实在无法修改输入的JSON,也可以让Jackson允许未转义的控制字符,但这会违反JSON规范,可能带来兼容性或安全问题,仅作为临时兼容方案使用:
ObjectMapper mapper = new ObjectMapper(); // 开启允许未转义控制字符的选项 mapper.configure(com.fasterxml.jackson.core.JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true); // 现在可以解析包含未转义控制字符的JSON YourTargetClass result = mapper.readValue(rawJson, YourTargetClass.class);
内容的提问来源于stack exchange,提问作者I_dont_know




