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

不使用Newtonsoft.Json解决Dictionary<string,object>接收ValueKind问题

问题根因

System.Text.Json默认反序列化object类型属性/字段时,不会自动推断JSON值对应的原始CLR类型,会将所有值封装为JsonElement结构体,你看到的ValueKind = String : "test"就是JsonElement的调试展示信息,其中ValueKind是该结构体用来标记JSON值类型的枚举属性。

仅使用内置System.Text.Json的解决方案

无需引入Newtonsoft.Json等第三方库,根据你使用的.NET版本选择对应方案即可:

  • 方案1:手动转换JsonElement(兼容所有.NET Core 3.0+版本,最小代码改动)
    字典中存储的object值实际运行时类型就是JsonElement,直接按照ValueKind枚举调用对应取值方法,就能拿到原始类型值,通用转换逻辑参考:
    // 递归转换嵌套JsonElement的辅助方法
    private static object? ConvertJsonElement(JsonElement element)
    {
        return element.ValueKind switch
        {
            JsonValueKind.String => element.GetString(),
            JsonValueKind.Number when element.TryGetInt32(out int intVal) => intVal,
            JsonValueKind.Number when element.TryGetInt64(out long longVal) => longVal,
            JsonValueKind.Number when element.TryGetDecimal(out decimal decVal) => decVal,
            JsonValueKind.Number => element.GetDouble(),
            JsonValueKind.True => true,
            JsonValueKind.False => false,
            JsonValueKind.Null => null,
            JsonValueKind.Array => element.EnumerateArray().Select(ConvertJsonElement).ToList(),
            JsonValueKind.Object => JsonSerializer.Deserialize<Dictionary<string, object?>>(element.GetRawText()),
            _ => element.GetRawText()
        };
    }
    
    // 在接口方法中直接转换参数字典
    [HttpPost]
    [Route("ExecProc/{SPname}")]
    public IActionResult ExecProc(string SPname, [FromBody] Dictionary<string, object?> parameters)
    {
        var rawParams = parameters.ToDictionary(
            kv => kv.Key,
            kv => kv.Value is JsonElement el ? ConvertJsonElement(el) : kv.Value
        );
        // 后续使用rawParams作为原始参数调用存储过程即可
    }
    
  • 方案2:全局配置序列化选项自动转换(.NET 5+ 支持,一次配置全局生效)
    .NET 5开始System.Text.Json新增了未知类型处理配置,配置后反序列化object类型时会自动转换为对应CLR类型,不需要手动写转换逻辑。在Program.cs中修改控制器的Json配置:
    builder.Services.AddControllers()
        .AddJsonOptions(opts =>
        {
            // 反序列化未知类型(object)时自动转换为基础类型/JsonNode
            opts.JsonSerializerOptions.UnknownTypeHandling = JsonUnknownTypeHandling.JsonNode;
            // 支持数字、日期等类型的宽松读取,适配前端传参格式差异
            opts.JsonSerializerOptions.NumberHandling = JsonNumberHandling.AllowReadingFromString;
        });
    
    配置完成后,接口接收的字典值会自动映射:JSON字符串对应string类型、布尔值对应bool类型、数字根据值范围自动映射为int/long/double/decimal、嵌套对象对应JsonObject、数组对应JsonArray,可以直接取值使用。
  • 方案3:自定义Object类型JsonConverter
    如果需要统一转换规则(比如所有数字都转为decimal适配存储过程参数要求),可以实现自定义JsonConverter<object?>,在Read方法中编写自定义的类型映射逻辑,注册到全局JsonSerializerOptions.Converters集合中即可完全控制反序列化行为。

注意:.NET Core 3.1版本没有内置UnknownTypeHandling配置,只能使用方案1的手动转换方式实现需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 11:15:42