不使用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配置:
配置完成后,接口接收的字典值会自动映射:JSON字符串对应builder.Services.AddControllers() .AddJsonOptions(opts => { // 反序列化未知类型(object)时自动转换为基础类型/JsonNode opts.JsonSerializerOptions.UnknownTypeHandling = JsonUnknownTypeHandling.JsonNode; // 支持数字、日期等类型的宽松读取,适配前端传参格式差异 opts.JsonSerializerOptions.NumberHandling = JsonNumberHandling.AllowReadingFromString; });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
相关产品推荐
相关产品推荐

