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

System.Text.Json动态类型处理:自定义object属性反序列化优化

解决System.Text.Json反序列化Dictionary<string, object>时转为JsonElement的问题

针对你在Blazor动态数据绑定中遇到的问题,这里提供两种简洁的解决方案:

方案一:自定义JsonConverter,反序列化时直接转为真实.NET类型

创建一个专门处理Dictionary<string, object>的Json转换器,在反序列化阶段自动将JsonElement转换为对应的.NET原生类型,无需后续手动处理:

public class ObjectDictionaryConverter : JsonConverter<Dictionary<string, object>>
{
    public override Dictionary<string, object> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        if (reader.TokenType != JsonTokenType.StartObject)
        {
            throw new JsonException("Expected start of object");
        }

        var dictionary = new Dictionary<string, object>();
        while (reader.Read())
        {
            if (reader.TokenType == JsonTokenType.EndObject)
            {
                return dictionary;
            }

            if (reader.TokenType != JsonTokenType.PropertyName)
            {
                throw new JsonException("Expected property name");
            }

            string propertyName = reader.GetString();
            reader.Read();

            dictionary[propertyName] = ReadValue(ref reader, options);
        }

        throw new JsonException("Unexpected end of JSON");
    }

    private object ReadValue(ref Utf8JsonReader reader, JsonSerializerOptions options)
    {
        return reader.TokenType switch
        {
            JsonTokenType.String => reader.GetString(),
            JsonTokenType.Number when reader.TryGetInt64(out long l) => l,
            JsonTokenType.Number when reader.TryGetDouble(out double d) => d,
            JsonTokenType.True => true,
            JsonTokenType.False => false,
            JsonTokenType.Null => null,
            JsonTokenType.StartArray => JsonSerializer.Deserialize<List<object>>(ref reader, options),
            JsonTokenType.StartObject => JsonSerializer.Deserialize<Dictionary<string, object>>(ref reader, options),
            _ => throw new JsonException($"Unsupported token type: {reader.TokenType}")
        };
    }

    public override void Write(Utf8JsonWriter writer, Dictionary<string, object> value, JsonSerializerOptions options)
    {
        JsonSerializer.Serialize(writer, value, options);
    }
}

使用方式

在反序列化时,将转换器添加到JsonSerializerOptions中:

var options = new JsonSerializerOptions();
options.Converters.Add(new ObjectDictionaryConverter());

var result = await httpClient.GetFromJsonAsync<DynamicDataGridResult>("your-api-url", options);

这样反序列化后的Data属性里的对象就直接是对应类型(string、int、bool等),无需再做后处理。

方案二:封装后处理逻辑,用扩展方法简化类型转换

如果不想自定义转换器,可以写一个通用的扩展方法来处理JsonElement到.NET类型的转换,避免重复的类型判断:

public static class JsonElementExtensions
{
    public static object ConvertToObject(this JsonElement element)
    {
        return element.ValueKind switch
        {
            JsonValueKind.String => element.GetString(),
            JsonValueKind.Number when element.TryGetInt64(out long l) => l,
            JsonValueKind.Number when element.TryGetDouble(out double d) => d,
            JsonValueKind.True => true,
            JsonValueKind.False => false,
            JsonValueKind.Null => null,
            JsonValueKind.Array => element.EnumerateArray().Select(e => e.ConvertToObject()).ToList(),
            JsonValueKind.Object => element.EnumerateObject()
                .ToDictionary(p => p.Name, p => p.Value.ConvertToObject()),
            _ => throw new NotSupportedException($"Unsupported JsonValueKind: {element.ValueKind}")
        };
    }
}

使用方式

遍历Data中的字典,批量转换值:

foreach (var dict in result.Data)
{
    foreach (var key in dict.Keys.ToList())
    {
        if (dict[key] is JsonElement element)
        {
            dict[key] = element.ConvertToObject();
        }
    }
}

这样只需要维护这一个扩展方法,后续新增类型支持也只需要在switch里添加即可,大幅降低重复代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 09:05:53