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容器:
- 创建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(); } }
- 修改GraphQL Schema,将原枚举定义替换为自定义Scalar:
type Media { name: String type: MediaType } scalar MediaType
注意事项
- 方案一优先推荐,仅需修改Java枚举类,侵入性低且实现简单。
- 若使用方案二,需确保客户端查询时传入的
type值与自定义Scalar的解析逻辑匹配,避免转换错误。
内容的提问来源于stack exchange,提问作者Joseph Freeman
相关产品推荐
相关产品推荐

