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

.NET Core GraphQL返回Dictionary反序列化异常的更优处理方案咨询

解决Blazor WebAssembly中GraphQL返回数组无法反序列化为Dictionary的问题

针对你遇到的GraphQL返回JSON数组无法反序列化为Dictionary<string, decimal>的问题,除了Newtonsoft序列化转换器,还有以下更贴合Blazor生态或更彻底的解决方案:

1. 调整GraphQL后端的字段输出格式(最优解)

问题根源在于后端将Dictionary序列化为了JSON数组(如[{"Key":"x","Value":1.0},...]),而客户端期望的是JSON对象格式(如{"x":1.0,...})。如果能控制后端代码,直接修改GraphQL的字段序列化逻辑是最彻底的解决方式:

  • 若使用HotChocolate等GraphQL框架,可为SomeClass的Items字段配置自定义解析器或类型映射,强制输出JSON对象而非数组。
  • 示例(HotChocolate):
    public class SomeClassType : ObjectType<SomeClass>
    {
        protected override void Configure(IObjectTypeDescriptor<SomeClass> descriptor)
        {
            descriptor.Field(f => f.Items)
                .Type<ObjectType<Dictionary<string, decimal>>>()
                .Resolve(ctx => ctx.Parent<SomeClass>().Items);
        }
    }
    
    这样后端直接输出客户端期望的JSON对象格式,无需修改任何客户端代码。

2. 使用System.Text.Json自定义转换器(贴合Blazor默认生态)

Blazor WebAssembly默认使用System.Text.Json,编写专属转换器比引入Newtonsoft更轻量且性能更优:

  • 首先实现转换器:
    public class DictionaryFromArrayConverter : JsonConverter<Dictionary<string, decimal>>
    {
        public override Dictionary<string, decimal> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            if (reader.TokenType != JsonTokenType.StartArray)
                throw new JsonException("JSON格式错误:预期为数组类型");
    
            var dictionary = new Dictionary<string, decimal>();
            while (reader.Read() && reader.TokenType != JsonTokenType.EndArray)
            {
                // 解析数组中的键值对对象
                reader.Read(); // 进入对象
                reader.Read(); // 读取"Key"属性名
                reader.Read(); // 获取Key值
                var key = reader.GetString();
                
                reader.Read(); // 读取"Value"属性名
                reader.Read(); // 获取Value值
                var value = reader.GetDecimal();
                
                dictionary[key] = value;
                reader.Read(); // 退出当前对象
            }
            return dictionary;
        }
    
        public override void Write(Utf8JsonWriter writer, Dictionary<string, decimal> value, JsonSerializerOptions options)
        {
            // 若需要序列化字典,可按原逻辑或转为数组,按需实现
            JsonSerializer.Serialize(writer, value, options);
        }
    }
    
  • 然后在Program.cs中全局注册转换器(以GraphQL.Client为例):
    builder.Services.AddGraphQLClient(options =>
    {
        options.EndPoint = new Uri("https://your-graphql-api-url");
        options.JsonSerializerOptions.Converters.Add(new DictionaryFromArrayConverter());
    });
    
    注册后所有涉及Dictionary<string, decimal>的反序列化都会自动适配数组格式。

3. 中间层DTO映射(轻量局部解决方案)

若不想修改全局序列化配置,可创建客户端专用DTO,手动完成格式转换:

  • 定义DTO类:
    public class SomeClassDto
    {
        public int Id { get; set; }
        public List<KeyValuePair<string, decimal>> Items { get; set; }
    }
    
  • 查询后转换为目标类型:
    var queryResult = await graphQLClient.SendQueryAsync<SomeClassDto>(yourGetDataQuery);
    var targetObject = new SomeClass
    {
        Id = queryResult.Data.Id,
        Items = queryResult.Data.Items.ToDictionary(kv => kv.Key, kv => kv.Value)
    };
    
    该方案逻辑直观,仅需在使用处做局部转换,适合数据模型使用范围有限的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 00:13:13