You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot Rest Client处理非法UTF-8字符0x86的问题

解决RestTemplate解析含非法UTF-8字符JSON的问题

针对你遇到的HttpMessageNotReadableException(JSON解析错误:Invalid UTF-8 start byte 0x86),可以通过以下几种方式处理非法UTF-8字符:

方案一:配置Jackson忽略非法UTF-8字符

修改RestTemplate的消息转换器,让Jackson的JSON解析器忽略无效UTF-8字节:

@Bean
fun restTemplate(): RestTemplate {
    val restTemplate = RestTemplate()
    // 获取或创建Jackson消息转换器
    val jacksonConverter = restTemplate.messageConverters
        .filterIsInstance<MappingJackson2HttpMessageConverter>()
        .firstOrNull() ?: MappingJackson2HttpMessageConverter()

    // 配置ObjectMapper的解析器容错规则
    val parserFactory = JsonFactory.builder()
        // 关键配置:允许解析无效的JSON UTF-8字节
        .enable(JsonParser.Feature.ALLOW_INVALID_FOR_JSON)
        .enable(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS)
        .build()
    jacksonConverter.objectMapper.factory = parserFactory

    // 更新RestTemplate的转换器列表
    if (restTemplate.messageConverters.contains(jacksonConverter)) {
        restTemplate.messageConverters.remove(jacksonConverter)
    }
    restTemplate.messageConverters.add(0, jacksonConverter)

    return restTemplate
}

方案二:拦截响应流过滤非法字符

自定义请求拦截器,提前清理响应中的无效UTF-8字符:

class InvalidUtf8CleaningInterceptor : ClientHttpRequestInterceptor {
    override fun intercept(
        request: HttpRequest,
        body: ByteArray,
        execution: ClientHttpRequestExecution
    ): ClientHttpResponse {
        val originalResponse = execution.execute(request, body)
        // 读取响应内容并过滤非法控制字符
        val cleanedContent = originalResponse.body?.use { inputStream ->
            InputStreamReader(inputStream, Charsets.UTF_8)
                .readText()
                .replace(Regex("[\\x00-\\x1F\\x7F-\\x9F]"), "")
        } ?: ""

        // 返回包装后的响应流
        return object : ClientHttpResponse by originalResponse {
            override fun getBody(): InputStream = ByteArrayInputStream(cleanedContent.toByteArray(Charsets.UTF_8))
        }
    }
}

注册拦截器到RestTemplate:

@Bean
fun restTemplate(): RestTemplate {
    val restTemplate = RestTemplate()
    restTemplate.interceptors.add(InvalidUtf8CleaningInterceptor())
    return restTemplate
}

方案三:指定响应的实际编码

如果API实际返回的是其他编码(如ISO-8859-1),强制RestTemplate用对应编码解析:

@Bean
fun restTemplate(): RestTemplate {
    val restTemplate = RestTemplate()
    // 替换字符串转换器为指定编码
    val stringConverter = StringHttpMessageConverter(Charset.forName("ISO-8859-1"))
    restTemplate.messageConverters.removeIf { it is StringHttpMessageConverter }
    restTemplate.messageConverters.add(0, stringConverter)

    // 配置Jackson转换器适配编码
    val jacksonConverter = MappingJackson2HttpMessageConverter()
    jacksonConverter.supportedMediaTypes = listOf(MediaType.APPLICATION_JSON)
    restTemplate.messageConverters.add(jacksonConverter)

    return restTemplate
}

选择建议

  • 方案一最简洁,利用Jackson原生容错能力,不修改原始响应内容
  • 方案二适合需要主动净化内容的场景,会清理掉所有控制类非法字符
  • 方案三仅适用于API明确使用非UTF-8编码的情况,需先确认响应编码

内容的提问来源于stack exchange,提问作者Donovan Wallace

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 22:45:57