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

GraphQL SPQR返回Null值问题:如何确保使用Jackson而非Gson?

解决SPQR使用Jackson而非Gson进行序列化的问题

问题背景

我们在Spring Boot应用中已配置Jackson ObjectMapper,设置SerializationInclusion.NON_NULL避免返回Null值,但直接通过SPQR返回实体给前端时仍出现Null值。本地用Jackson转换实体时无Null值,且项目因其他依赖引入了Gson,怀疑SPQR优先使用了Gson而非自定义的Jackson配置。SPQR版本从0.12.1升级到0.12.3后问题依旧。

解决方案

1. 强制SPQR使用自定义Jackson ObjectMapper

SPQR会根据类路径中的序列化库自动选择实现,当Gson存在时可能优先选用。要强制指定使用你的自定义Jackson配置,需在构建GraphQLSchemaGenerator时显式传入ObjectMapper:

import io.leangen.graphql.GraphQLSchemaGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class GraphQLConfig {

    @Autowired
    private ObjectMapper customObjectMapper; // 注入BootstrapConfig中定义的ObjectMapper

    @Bean
    public GraphQLSchema graphQLSchema() {
        return new GraphQLSchemaGenerator()
                .withObjectMapper(customObjectMapper) // 关键:指定SPQR使用Jackson序列化
                .withOperationsFromSingleton(new EntityMutation()) // 替换为你的业务实现类
                // 其他SPQR配置(如添加查询类、自定义类型等)
                .generate();
    }
}

2. 排除不必要的Gson依赖(可选)

如果项目中不需要Gson,可以通过Gradle排除其他依赖引入的Gson,从根源避免SPQR选择它:

// 针对单个依赖排除Gson
implementation('com.example:some-dependency:1.0.0') {
    exclude group: 'com.google.code.gson', module: 'gson'
}

// 全局排除Gson(谨慎使用,确保不会影响其他依赖)
configurations.all {
    exclude group: 'com.google.code.gson', module: 'gson'
}

3. 确保自定义Jackson实例为Spring容器首选

在BootstrapConfig的ObjectMapper Bean上添加@Primary注解,保证Spring注入的是你的自定义实例,而非默认生成的:

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.text.SimpleDateFormat;
import java.util.Locale;
import java.util.TimeZone;

@Configuration
public class BootstrapConfig {

    private static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";

    @Primary // 标记为首选ObjectMapper
    @Bean
    public ObjectMapper objectMapper() {
        final SimpleDateFormat zuluDateFormat = new SimpleDateFormat(DATE_FORMAT, Locale.US);
        zuluDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
        final ObjectMapper jsonMapper = new ObjectMapper();
        jsonMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
        jsonMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        jsonMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        jsonMapper.registerModule(new JavaTimeModule());
        jsonMapper.setDateFormat(zuluDateFormat);
        jsonMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

        return jsonMapper;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 16:56:07