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

Spring Boot跨服务代理转发请求Jackson反序列化异常求助

问题分析与解决方案

首先咱们拆解下你遇到的问题本质:

当直接从InputStream解析到MyPojo时失败,但先把流转成String再解析就成功,这个异常Can not construct instance of...no String-argument constructor/factory method说明Jackson拿到的请求体其实是一个被当成字符串的JSON内容——简单说,请求体不是原始的JSON对象(比如{"name":"test"}),而是一个被引号包裹的字符串(比如"{\"name\":\"test\"}")。

Jackson看到这种内容时,会默认尝试用MyPojo的字符串构造方法实例化,但你的POJO没有这个构造方法,所以报错。而先转成String再解析,相当于去掉了外层的引号,得到真正的JSON对象内容,自然就能正常解析。

核心原因排查

最可能的问题出在Web应用发送请求的方式上:你把POJO转成JSON字符串后,直接把这个字符串作为请求体发送了。这种情况下,请求体本身会被当成纯文本字符串,还会被自动添加引号转义,导致微服务端接收到的是字符串形式的JSON,而非原生JSON结构。

解决方案

1. 从源头修正请求发送方式(推荐)

不要手动把POJO转成字符串再发送,直接让HTTP客户端(比如RestTemplate、WebClient)负责序列化POJO为JSON:

比如用RestTemplate的正确写法:

// 直接传入POJO,RestTemplate会自动用ObjectMapper序列化,同时设置Content-Type为application/json
MyPojo myPojo = new MyPojo();
// ... 设置POJO属性

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<MyPojo> requestEntity = new HttpEntity<>(myPojo, headers);

restTemplate.exchange("你的微服务API地址", HttpMethod.POST, requestEntity, 响应类型.class);

如果你之前是下面这种错误写法,一定要改掉:

// 错误写法:把JSON字符串直接作为请求体,导致请求体是带引号的字符串
String jsonStr = objectMapper.writeValueAsString(myPojo);
restTemplate.postForObject("你的微服务API地址", jsonStr, 响应类型.class);

2. 检查代理转发逻辑

确认你的代理类在转发请求时,没有对请求体做额外的字符串处理(比如转义、包裹引号、修改Content-Type)。代理应该原样转发请求的字节流,并且保留原始的Content-Type: application/json请求头。

3. 微服务端的临时兼容方案(不推荐,仅应急)

如果暂时无法修改Web应用的发送逻辑,可以在微服务端统一处理这种情况,比如修改safeParseJSON方法:

public static <T> T safeParseJSON(ObjectMapper objectMapper, InputStream inputStream, Class<T> targetType) {
    try {
        // 先把流转成字符串
        String content = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
        // 判断是否是被引号包裹的JSON字符串
        if (content.startsWith("\"") && content.endsWith("\"")) {
            // 去掉首尾引号,还原转义字符
            content = content.substring(1, content.length() - 1);
            content = StringEscapeUtils.unescapeJson(content);
        }
        return objectMapper.readValue(content, targetType);
    } catch (IOException ex) {
        throw new RuntimeException(String.format("Unable to parse JSON payload - %s", ex.getMessage()), ex);
    }
}

不过这只是临时补丁,还是建议从发送端解决问题,避免后续出现更多兼容问题。

4. 确认请求头设置

Web应用发送请求时,必须设置Content-Type: application/json请求头。如果设置成text/plain或者其他类型,微服务端的Jackson会默认把请求体当作纯文本处理,从而引发解析问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 00:27:37