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

如何在GraphQL响应中排除值为Null的可空字段

GraphQL响应自动排除Null值可空字段的解决方案

问题背景

我基于Netflix DGS框架开发GraphQL服务,Schema中定义了非空字段和可空字段,需求是当可空字段值为Null时,自动从响应结果中排除。已在User模型类添加@JsonInclude(JsonInclude.Include.NON_NULL)注解,但无效,Null字段仍会出现在响应中。

相关代码片段

构建配置(build.gradle)

plugins {
    id 'java'
    id 'org.springframework.boot' version '2.7.17'
    id 'io.spring.dependency-management' version '1.0.15.RELEASE'
}

group = 'com.learntech'
version = '1.0.0-SNAPSHOT'

java {
    sourceCompatibility = '11'
}

dependencyManagement {
    imports {
        mavenBom 'com.netflix.graphql.dgs:graphql-dgs-platform-dependencies:5.5.5'
    }
}

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-webflux'
    implementation(platform("com.netflix.graphql.dgs:graphql-dgs-platform-dependencies:5.5.5"))
    implementation 'com.netflix.graphql.dgs:graphql-dgs-webflux-starter:5.5.5'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'com.h2database:h2'
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'io.projectreactor:reactor-test'
}

tasks.named('test') {
    useJUnitPlatform()
}

DataFetcher代码

@DgsComponent
@Slf4j
public class UserDataFetcher {

    private final UserSearchService userSearchService;

    public UserDataFetcher(UserSearchService userSearchService) {
        this.userSearchService = userSearchService;
    }

    @DgsQuery
    public Mono<List<User>> users(@InputArgument SearchInput searchInput) throws JsonProcessingException {
        log.info("users() Starts");
        log.info("First Name {}", searchInput.getFirstName());
        log.info("Last Name {}", searchInput.getLastName());

        List<User> users = userSearchService.searchUser(searchInput);
        return Mono.just(users);
    }

    @DgsQuery
    public Mono<User> user(@InputArgument UUID id){
        log.info("user() Starts");
        User user = userSearchService.searchById(id);
        return Mono.just(user);
    }
}

模型类

@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class User {
    private UUID id;
    private String firstName;
    private String lastName;
    private String dateOfBirth;
    private String gender;
    private List<Address> address;
    private List<Phone> phone;
}

Schema定义

type Query {
    users(searchInput: SearchInput) : [User]
    user(id : ID!): User
}

type UserResponse{
    users: [User]
}

type User {
    id: ID!
    firstName: String!
    lastName: String!
    dateOfBirth: String
    gender: String
    address: [Address]
    phone: [Phone]
}

type Address {
    type: String
    street1: String
    street2: String
    city: String
    state: String
    zip: Int
}

type Phone {
    type: String
    number: String
    countryCode: String
}

input SearchInput {
    firstName: String
    lastName: String
    dateOfBirth: String
}

请求与响应示例

请求:

{
    "query": "query { user(id: \"USERID\") { id firstName lastName dateOfBirth } }"
}

当前响应(不符合需求):

{
    "data": {
        "user": {
            "id": "2c628b4e-bef3-4794-9af5-5e8deb69817e",
            "firstName": "Jhon",
            "lastName": "Victor",
            "dateOfBirth": null // 该字段需从响应中排除
        }
    }
}

解决方案

DGS框架默认不直接使用Jackson的@JsonInclude规则处理GraphQL响应,需通过以下方式配置:

方法1:自定义DGS的ObjectMapper

创建配置类,修改DGS用于序列化响应的ObjectMapper,设置排除Null值:

@Configuration
public class DgsCustomConfiguration {

    @Bean
    public ObjectMapper dgsObjectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        // 若有嵌套对象,确保嵌套类也添加了@JsonInclude(NON_NULL)
        return objectMapper;
    }
}

方法2:配置GraphQL执行策略处理Null值

通过自定义执行策略,让GraphQL在构建响应时自动移除Null字段:

@Configuration
public class DgsNullValueHandlingConfig {

    @Bean
    public ExecutionStrategy executionStrategy() {
        return new AsyncExecutionStrategy(new DefaultFieldValueInfoFactory() {
            @Override
            public FieldValueInfo fieldValueInfo(Object value, GraphQLFieldDefinition fieldDefinition) {
                if (value == null) {
                    // 返回NULL标识,让GraphQL跳过该字段
                    return FieldValueInfo.NULL;
                }
                return super.fieldValueInfo(value, fieldDefinition);
            }
        });
    }
}

注意事项

  • 确保所有嵌套模型类(如Address、Phone)也添加@JsonInclude(JsonInclude.Include.NON_NULL)注解,避免嵌套Null字段出现在响应中。
  • 重启服务后重新测试,验证Null字段是否被自动排除。

预期响应效果

修改配置后,当dateOfBirth为Null时,响应将自动排除该字段:

{
    "data": {
        "user": {
            "id": "2c628b4e-bef3-4794-9af5-5e8deb69817e",
            "firstName": "Jhon",
            "lastName": "Victor"
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 23:17:03