Graphql Newtonsoft 序列化器在解析枚举时抛出错误

问题描述 投票:0回答:1

我在 Blazor Web 程序集应用程序中使用了 .NET Core GraphQL 后端服务,并使用带有如下枚举的

GetData
GraphQL 查询:

public enum SomeEnumTypes : byte
{
    None,
    First,
    SecondItem
} 

当数据从该查询中的后端返回时,枚举中的

SecondItem
作为
SECOND_ITEM
返回给客户端,但会导致错误:

Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
未处理的异常呈现组件:将值“SECOND_ITEM”转换为类型“SomeEnumTypes”时出错。路径“data.GetData[0].someEnumType”,第 1 行,位置 1375。

Newtonsoft.Json.JsonSerializationException:将值“SECOND_ITEM”转换为类型“SomeEnumTypes”时出错。路径“data.GetData[0].someEnumType”,第 1 行,位置 1375。

System.ArgumentException:找不到请求的值“SECOND_ITEM”。

在Newtonsoft.Json.Utilities.EnumUtils.ParseEnum(类型enumType,NamingStrategynamingStrategy,字符串值,布尔disallowNumber)
在Newtonsoft.Json.Converters.StringEnumConverter.ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化器)

SomeEnumTypes
枚举位于第三方 nuget 库中,因此我无法直接对枚举进行任何更改。

我尝试了多种方法,包括使用正则表达式为 Newtonsoft 序列化器编写自定义转换器来处理下划线,甚至为该枚举创建一个字典以在转换器中进行转换,但没有用。

_graphqlClient = new GraphQLHttpClient(_configuration.GetValue<string>("SomeKey"), new NewtonsoftJsonSerializer(options =>
{
    options.Converters.Add(new SomeConverter())
}));

我有什么遗漏的吗?如有帮助,我们将不胜感激。

c# .net-core graphql json.net
1个回答
0
投票

您似乎在 GraphQL 客户端中发现了一个错误

  1. Json.NET 按照转换器添加到

    JsonSerializerSettings.Converters
    列表的顺序应用转换器。

  2. NewtonsoftJsonSerializer
    将转换器
    ConstantCaseEnumConverter
    添加到列表的 beginning,从而取代您添加到末尾的
    SomeConverter
    转换器。

  3. ConstantCaseEnumConverter
    坏了:

    • 它在 CONSTANT_CASE 中序列化枚举,但它在没有任何大小写策略的情况下反序列化它们,因此像
      SecondItem
      =>
      SECOND_ITEM
      这样的枚举值无法往返。
    • 它对
      [Flags]
      枚举错误地应用了大小写策略,应该用逗号分隔,如下所示:
      "FLAG_ITEM_ONE, FLAG_ITEM_THREE"

老实说,我不明白为什么 GraphQL 以这种方式实现他们的转换器,因为创建一个常量案例命名策略并将其设置为

StringEnumConverter.NamingStrategy
会简单得多。 我只能猜测他们想禁用对
EnumMemberAttribute
的支持,而
SystemTextJsonSerializer
不支持。

作为解决方法,您可以创建一个固定的枚举转换器并将其插入转换器列表的beginning

只要您没有将

[EnumMember("some name")]
应用于任何枚举,创建固定转换器的最简单方法就是创建您自己的自定义命名策略并将其与 Newtonsoft 的内置
StringEnumConverter
:

一起使用
using GraphQL.Client.Abstractions.Utilities;

public sealed class ConstantCaseNamingStrategy : NamingStrategy
{
    protected override string ResolvePropertyName(string name) => name.ToConstantCase();
}

然后将其插入到开头,如下所示:

new NewtonsoftJsonSerializer(
    options => 
        options.Converters.Insert(
            0, new StringEnumConverter(new ConstantCaseNamingStrategy())));

您应该能够成功往返您的

SomeEnumTypes

模型小提琴在这里

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.