
当Feign客户端调用返回纯文本(如字符串"OK")而非标准JSON的接口时,默认JSON解码器会解析失败;需自定义Decoder跳过JSON反序列化,直接提取响应体字符串。
当Feign客户端调用返回纯文本(如字符串"OK")而非标准JSON的接口时,默认JSON解码器会解析失败;需自定义Decoder跳过JSON反序列化,直接提取响应体字符串。
在使用 Spring Cloud OpenFeign 调用第三方服务时,若该服务仅返回简单字符串(例如 HTTP 200 响应体为纯文本 "OK"),而 Feign 默认配置的 JacksonDecoder 会尝试将其作为 JSON 解析,就会抛出类似以下异常:
feign.FeignException: Unrecognized token 'OK': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false')
这是因为 JacksonDecoder 严格要求响应体符合 JSON 语法结构,而纯文本 "OK" 不是合法的 JSON 字符串(缺少外层引号或非 JSON 格式)。
✅ 正确解决方案:自定义 Feign Decoder
你需要替换默认的 Decoder,使用一个能处理 text/plain 响应并直接返回 String 的轻量级解码器。推荐实现如下:
@Bean
public Decoder feignStringDecoder() {
return new Decoder.Default() {
@Override
public Object decode(Response response, Type type) throws IOException {
if (type == String.class) {
return Util.toString(response.body().asReader(StandardCharsets.UTF_8));
}
// 对其他类型仍委托给默认行为(可选)
return super.decode(response, type);
}
};
}
⚠️ 注意:此 Bean 需定义在 @Configuration 类中,并确保其作用域覆盖对应 @FeignClient(例如通过 @FeignClient(configuration = ...) 显式指定,或全局生效)。
? FeignClient 接口定义优化建议
保持接口签名简洁明确,无需手动加 @ResponseStatus 或 produces(Feign 不依赖它做解码):
@FeignClient(name = "external-api", url = "https://api.example.com", configuration = FeignConfig.class)
public interface ExternalApiFeignClient {
@PostMapping(value = "/url", consumes = MediaType.APPLICATION_JSON_VALUE)
String apiService(@RequestBody MyDTO dto);
}
其中 FeignConfig.class 是包含上述 feignStringDecoder() Bean 的配置类。
? 关键注意事项
-
不要在方法上标注
produces = TEXT_PLAIN_VALUE:Feign 的produces属性仅影响请求头Accept,不控制响应解码逻辑; - *确保响应 Content-Type 为
text/plain或 `text/**:若服务实际返回application/json但内容却是"OK"`,需先确认服务端是否误设了 Content-Type; -
避免过度泛化解码器:上述
Decoder仅对String.class特殊处理,其余类型(如自定义 DTO)仍交由 Jackson 处理,保障兼容性; -
日志调试技巧:启用 Feign 日志(
logging.level.feign=DEBUG)可查看原始响应体与 Content-Type,快速定位格式问题。
通过定制 Decoder,你无需修改不可控的外部服务,即可健壮、清晰地集成返回纯文本的 API,这是微服务间异构协议对接的典型实践。










