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

Spring Gateway响应转换过滤器报错:不支持application/json转JsonNode

Spring Gateway响应转换过滤器媒体类型不支持问题解决

问题场景

使用Spring Gateway构建代理服务,编写了响应转换过滤器,但运行时抛出媒体类型不支持的错误。

过滤器代码

import com.fasterxml.jackson.databind.JsonNode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.rewrite.ModifyResponseBodyGatewayFilterFactory;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

@Slf4j
@Component
public class ResponseTransformationGatewayFilterFactory extends AbstractGatewayFilterFactory<ResponseTransformationGatewayFilterFactory.Config> {

    public ResponseTransformationGatewayFilterFactory() {
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {
        ModifyResponseBodyGatewayFilterFactory.Config modifyConfig = new ModifyResponseBodyGatewayFilterFactory.Config();
// used string.class but same issue
        modifyConfig.setRewriteFunction(JsonNode.class, JsonNode.class, (exchange, originalResponseBody) -> {
            // Transform the response body
            JsonNode transformedBody = transformResponseBody(originalResponseBody);
            return Mono.just(transformedBody);
        });
        return new ModifyResponseBodyGatewayFilterFactory(new ArrayList<>(), new HashSet<>(), new HashSet<>()).apply(modifyConfig);
    }

    private JsonNode transformResponseBody(JsonNode originalBody) {
        // we can get rid of fields here.

        return JsonResponseFilter.filter(originalBody, List.of("options"));

        // only add options with included providers

    }

    public static class Config {
    }
}

报错信息

org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'application/json' not supported for bodyType=com.fasterxml.jackson.databind.JsonNode
    at org.springframework.web.reactive.function.BodyExtractors.readWithMessageReaders(BodyExtractors.java:205) ~[spring-webflux-6.0.12.jar:6.0.12]
    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
    *__checkpoint ⇢ Body from UNKNOWN  [DefaultClientResponse]

解决方法

1. 依赖注入ModifyResponseBodyGatewayFilterFactory

你手动实例化ModifyResponseBodyGatewayFilterFactory时,传入的空集合导致它无法加载默认的消息转换器(比如Jackson的JSON转换器)。正确的做法是让Spring容器管理这个工厂类,通过构造注入获取实例:

修改后的过滤器代码:

import com.fasterxml.jackson.databind.JsonNode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.rewrite.ModifyResponseBodyGatewayFilterFactory;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import java.util.List;

@Slf4j
@Component
public class ResponseTransformationGatewayFilterFactory extends AbstractGatewayFilterFactory<ResponseTransformationGatewayFilterFactory.Config> {

    private final ModifyResponseBodyGatewayFilterFactory modifyResponseBodyFilterFactory;

    // 构造注入Spring容器管理的工厂实例
    public ResponseTransformationGatewayFilterFactory(ModifyResponseBodyGatewayFilterFactory modifyResponseBodyFilterFactory) {
        super(Config.class);
        this.modifyResponseBodyFilterFactory = modifyResponseBodyFilterFactory;
    }

    @Override
    public GatewayFilter apply(Config config) {
        ModifyResponseBodyGatewayFilterFactory.Config modifyConfig = new ModifyResponseBodyGatewayFilterFactory.Config();
        modifyConfig.setRewriteFunction(JsonNode.class, JsonNode.class, (exchange, originalResponseBody) -> {
            JsonNode transformedBody = transformResponseBody(originalResponseBody);
            return Mono.just(transformedBody);
        });
        // 使用注入的工厂类创建过滤器
        return modifyResponseBodyFilterFactory.apply(modifyConfig);
    }

    private JsonNode transformResponseBody(JsonNode originalBody) {
        return JsonResponseFilter.filter(originalBody, List.of("options"));
    }

    public static class Config {
    }
}

2. 确保Jackson依赖存在

检查项目依赖,确保jackson-databind和spring-boot-starter-webflux已经引入(Spring Gateway默认依赖webflux,通常会自动引入Jackson,但如果缺失需要手动添加):

Maven依赖示例:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

3. 可选:显式指定支持的媒体类型

如果仍有问题,可以在配置中显式指定支持的媒体类型,确保过滤器只处理JSON格式的响应:

import org.springframework.http.MediaType;
import java.util.List;

// 在apply方法中添加
modifyConfig.setSupportedMediaTypes(List.of(MediaType.APPLICATION_JSON));

原因说明

手动创建ModifyResponseBodyGatewayFilterFactory实例时,传入的空messageReaders、messageWriters集合会导致工厂无法加载Spring默认配置的JSON消息转换器,因此无法将application/json类型的响应体转换为JsonNode对象。通过依赖注入获取的工厂实例会自动加载这些转换器,从而解决媒体类型不支持的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 16:15:21