Error while extracting response for type [] and content type [],json返回值被解析为xml

在使用restTemplate请求restful接口时,在特定情况下总会将返回的json数据解析为xml数据然后处理,接着就会爆出标题中的错误:

Error while extracting response for type [] and content type [application/xml;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unexpected character '5' (code 53) in content after '<' (malformed start element?).
 at [row,col {unknown-source}]: [1,15395]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Unexpected character '5' (code 53) in content after '<' (malformed start element?).

根据错误信息来看,似乎响应头标记了返回类型为[application/xml;charset=UTF-8],然而实际情况是所有的返回数据都是[application/json;charset=UTF-8]。

跟踪restTemplate源码,发现由new RestTemplate(httpRequestFactory())创建的实例会有7个converter:

 继续跟踪restTemplate的exchange,当对response进行类型转换时,会迭代当前实例中所有的converter,然后选择一个支持当前类型的converter执行,使用canRead来判断:

此时就发现了问题,在特定情况下,响应头的contentType被读作了"application/xml",然而此时的真实数据仍然为json格式。所以将用于xml格式的converter删除,则迭代器会寻找下一个可执行的converter即MappingJackson2HttpMessageConverter。或者将二者顺序换一下,降低xml的优先级。

解决办法:

方案1:删除xml的转换器

    @Bean
    public RestTemplate restTemplate() {
        RestTemplate template = new RestTemplate(httpRequestFactory());
        // 排除掉xml的解析converter,避免将json数据当做xml解析
        List<HttpMessageConverter<?>> collect = template.getMessageConverters().stream()
                                                        .filter(m -> !(m instanceof MappingJackson2XmlHttpMessageConverter))
                                                        .collect(Collectors.toList());
        template.setMessageConverters(collect);
        return template;
    }

方案2:降低xml转换器优先级

    @Bean
    public RestTemplate restTemplate() {
        RestTemplate template = new RestTemplate(httpRequestFactory());
        // 将xml解析的优先级调低
        int xml = 0, json = 0;
        List<HttpMessageConverter<?>> messageConverters = template.getMessageConverters();
        for (int i = 0; i < messageConverters.size(); i++) {
            HttpMessageConverter<?> h = messageConverters.get(i);
            if (h instanceof MappingJackson2XmlHttpMessageConverter) {
                xml = i;
            } else if (h instanceof MappingJackson2HttpMessageConverter) {
                json = i;
            }
        }
        Collections.swap(template.getMessageConverters(), xml, json);

        return template;
    }

当Feign接口调用出现 `error while extracting response for type... and content type [application/json]` 异常时,可尝试以下解决办法: ### 检查响应数据与目标类型是否匹配 确保服务端返回的JSON数据结构与Feign客户端期望接收的类型一致。例如,如果服务端返回的是JSON数组,而客户端期望的是单个对象,就会出现转换异常。 ```java // 假设服务端返回JSON数组 // 错误示例:期望单个对象 @FeignClient(name = "example-service") public interface ExampleFeignClient { @GetMapping("/data") ExampleData getData(); } // 正确示例:期望数组 @FeignClient(name = "example-service") public interface ExampleFeignClient { @GetMapping("/data") List<ExampleData> getData(); } ``` ### 检查JSON解析器配置 Feign默认使用Jackson进行JSON解析,确保Jackson配置正确,并且能够处理服务端返回的JSON数据。可以自定义Feign的解码器来配置Jackson。 ```java import feign.codec.Decoder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import feign.jackson.JacksonDecoder; @Configuration public class FeignConfig { @Bean public Decoder feignDecoder() { return new JacksonDecoder(new MappingJackson2HttpMessageConverter()); } } ``` ### 确保实体类有合适的构造函数 如果实体类没有无参构造函数或者合适的反序列化构造函数,Jackson在解析JSON数据时会报错。确保实体类有默认的无参构造函数,或者提供带有必要参数的构造函数并使用 `@JsonCreator` 和 `@JsonProperty` 注解。 ```java import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; public class ExampleData { private String name; private int age; @JsonCreator public ExampleData(@JsonProperty("name") String name, @JsonProperty("age") int age) { this.name = name; this.age = age; } // Getters and setters public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } ``` ### 处理响应状态码 如果服务端返回的状态码不是200,Feign可能会抛出异常。可以自定义错误解码器来处理不同的状态码。 ```java import feign.Response; import feign.codec.ErrorDecoder; import org.springframework.stereotype.Component; @Component public class CustomErrorDecoder implements ErrorDecoder { @Override public Exception decode(String methodKey, Response response) { // 处理不同的状态码 switch (response.status()) { case 400: // 处理400错误 break; case 404: // 处理404错误 break; default: return new Exception("Generic error"); } return null; } } ``` ### 检查服务端响应内容 确保服务端返回的JSON数据格式正确,没有语法错误。可以使用工具(如Postman)直接调用服务端接口,查看返回的JSON数据。 ### 检查依赖版本 确保Feign、Spring Cloud等相关依赖的版本兼容。不同版本的依赖可能存在兼容性问题,导致JSON解析异常。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值