You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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

火山引擎 最新活动