GraphQL Newtonsoft序列化解析枚举时抛出错误求助
解决方案
问题出在后端返回的蛇形命名枚举值(如SECOND_ITEM)无法被默认序列化器映射到第三方库的帕斯卡命名枚举(如SecondItem),且你的自定义转换器可能存在逻辑缺陷或未正确覆盖默认行为。
核心问题分析
默认的StringEnumConverter不会自动将蛇形命名转换为帕斯卡命名,且如果你的自定义转换器未优先于默认转换器执行,会被默认逻辑覆盖,导致解析失败。
正确实现步骤
1. 编写自定义枚举转换器
实现一个能将蛇形命名字符串转换为帕斯卡命名枚举的转换器,同时支持可空枚举:
public class SnakeCaseToPascalEnumConverter : JsonConverter { public override bool CanConvert(Type objectType) { Type enumType = Nullable.GetUnderlyingType(objectType) ?? objectType; return enumType.IsEnum; } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null && Nullable.GetUnderlyingType(objectType) != null) { return null; } if (reader.TokenType != JsonToken.String) { throw new JsonSerializationException($"Unexpected token {reader.TokenType} when parsing enum."); } string snakeCaseValue = reader.Value.ToString(); Type enumType = Nullable.GetUnderlyingType(objectType) ?? objectType; // 将蛇形命名转为帕斯卡命名:SECOND_ITEM → SecondItem string pascalCaseName = string.Concat( snakeCaseValue.Split('_') .Select(part => part.Length > 0 ? char.ToUpper(part[0]) + part.Substring(1).ToLower() : string.Empty) ); // 尝试严格匹配解析 if (Enum.TryParse(enumType, pascalCaseName, out var result)) { return result; } // fallback到忽略大小写解析(可选) if (Enum.TryParse(enumType, pascalCaseName, ignoreCase: true, out result)) { return result; } throw new JsonSerializationException($"无法将值 '{snakeCaseValue}' 转换为枚举类型 '{enumType.Name}'."); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { if (value == null) { writer.WriteNull(); return; } Type enumType = value.GetType(); string enumName = Enum.GetName(enumType, value); // 将帕斯卡命名转为蛇形(如果需要客户端序列化枚举时也用蛇形格式) string snakeCaseName = string.Concat( enumName.Select((c, i) => i > 0 && char.IsUpper(c) ? "_" + char.ToUpper(c) : char.ToUpper(c).ToString()) ); writer.WriteValue(snakeCaseName); } }
2. 正确配置GraphQL客户端
配置时必须移除默认的StringEnumConverter,避免其优先执行,然后添加自定义转换器:
_graphqlClient = new GraphQLHttpClient(_configuration.GetValue<string>("SomeKey"), new NewtonsoftJsonSerializer(options => { // 移除默认的StringEnumConverter,避免冲突 var defaultEnumConverter = options.Converters.OfType<StringEnumConverter>().FirstOrDefault(); if (defaultEnumConverter != null) { options.Converters.Remove(defaultEnumConverter); } // 添加自定义转换器 options.Converters.Add(new SnakeCaseToPascalEnumConverter()); }));
3. 额外检查项
- 确保
GraphQL.Client.NewtonsoftJson包与Newtonsoft.Json版本兼容,避免版本冲突导致配置不生效 - 确认后端返回的枚举值格式确实为蛇形大写(如
SECOND_ITEM),无拼写错误
内容的提问来源于stack exchange,提问作者Ali Khan
相关产品推荐
相关产品推荐

