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
相关产品推荐
相关产品推荐

