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

Spring GraphQL枚举序列化问题:@JsonProperty未生效

Spring Boot 3.0.2 + Spring GraphQL 枚举序列化问题解决办法

问题描述

使用Spring Boot v3.0.2集成Spring GraphQL时,Java枚举类即使添加了Jackson的@JsonProperty注解指定序列化值,GraphQL查询结果仍返回枚举名称(如IMAGE),而非期望的自定义字符串(如img)。

相关代码如下:

GraphQL Schema

type Media { 
    name: String
    type: MediaType
}

enum MediaType {
    IMAGE
    VIDEO
}

Java枚举类

public enum MediaType {

    @JsonProperty("img")
    IMAGE("img"),
    @JsonProperty("video")
    VIDEO("video");

    private final String value;

    MediaType(String type) {
        this.value = type;
    }

    @Override
    public String toString() {
        return value;
    }
} 

实际查询结果

{
    "name": "My Media",
    "type": "IMAGE" // 期望返回"img"
}

原因分析

Spring GraphQL默认不依赖Jackson处理枚举序列化,而是直接将Java枚举名称与GraphQL Schema中定义的枚举值绑定,因此Jackson的@JsonProperty注解不会生效。

解决方案

方案一:使用Spring GraphQL原生@EnumValue注解

这是最简洁的解决方案,无需修改GraphQL Schema,只需给Java枚举的每个常量添加@EnumValue注解,指定对应的GraphQL返回值:

import org.springframework.graphql.data.method.annotation.EnumValue;

public enum MediaType {

    @EnumValue("img")
    IMAGE("img"),
    @EnumValue("video")
    VIDEO("video");

    private final String value;

    MediaType(String type) {
        this.value = type;
    }

    @Override
    public String toString() {
        return value;
    }
}

该注解同时支持序列化(返回自定义值)和反序列化(接收自定义值映射到枚举常量),完全匹配需求。

方案二:自定义GraphQL Scalar类型

若需要更灵活的控制(比如复杂的枚举转换逻辑),可以自定义GraphQL Scalar类型并注册到Spring容器:

  1. 创建Scalar配置类
import graphql.schema.Coercing;
import graphql.schema.GraphQLScalarType;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class GraphQLScalarConfig {

    @Bean
    public GraphQLScalarType mediaTypeScalar() {
        return GraphQLScalarType.newScalar()
                .name("MediaType")
                .description("Custom scalar for MediaType enum")
                .coercing(new Coercing<MediaType, String>() {
                    // 序列化:将枚举转为自定义字符串
                    @Override
                    public String serialize(Object dataFetcherResult) {
                        if (dataFetcherResult instanceof MediaType) {
                            return ((MediaType) dataFetcherResult).toString();
                        }
                        throw new IllegalArgumentException("Expected MediaType enum value");
                    }

                    // 解析客户端传入的变量值
                    @Override
                    public MediaType parseValue(Object input) {
                        if (input instanceof String) {
                            return switch ((String) input) {
                                case "img" -> MediaType.IMAGE;
                                case "video" -> MediaType.VIDEO;
                                default -> throw new IllegalArgumentException("Invalid MediaType value: " + input);
                            };
                        }
                        throw new IllegalArgumentException("Expected string input");
                    }

                    // 解析查询中的字面量值
                    @Override
                    public MediaType parseLiteral(Object input) {
                        return parseValue(input);
                    }
                })
                .build();
    }
}
  1. 修改GraphQL Schema,将原枚举定义替换为自定义Scalar:
type Media { 
    name: String
    type: MediaType
}

scalar MediaType

注意事项

  • 方案一优先推荐,仅需修改Java枚举类,侵入性低且实现简单。
  • 若使用方案二,需确保客户端查询时传入的type值与自定义Scalar的解析逻辑匹配,避免转换错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 00:41:12