C# API反序列化Dictionary<string,dynamic>遇JsonElement转换问题求方案
C# API Dictionary<string,dynamic>反序列化为原生类型解决方案
方案1:替换默认序列化器为Newtonsoft.Json
System.Text.Json作为ASP.NET Core默认序列化器,对dynamic类型的反序列化默认返回JsonElement对象,而Newtonsoft.Json会自动将JSON值映射为.NET原生类型,是最便捷的解决方案:
- 第一步:安装NuGet包
Microsoft.AspNetCore.Mvc.NewtonsoftJson - 第二步:修改服务注册配置(Program.cs示例):
var builder = WebApplication.CreateBuilder(args); // 注册控制器时添加Newtonsoft.Json支持 builder.Services.AddControllers() .AddNewtonsoftJson();
配置完成后,原有代码无需修改,incomingData中的值会直接反序列化为string、int等原生类型,不会再触发类型转换异常。
方案2:自定义System.Text.Json转换器(不更换序列化器)
如果需要保留System.Text.Json作为默认序列化器,可以自定义JsonConverter实现动态类型的自动转换:
- 实现自定义转换器:
using System.Text.Json; using System.Text.Json.Serialization; public class DynamicDictionaryConverter : JsonConverter<Dictionary<string, dynamic>> { public override Dictionary<string, dynamic>? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { using var doc = JsonDocument.ParseValue(ref reader); return ParseJsonElement(doc.RootElement); } private Dictionary<string, dynamic> ParseJsonElement(JsonElement element) { var result = new Dictionary<string, dynamic>(); foreach (var property in element.EnumerateObject()) { result[property.Name] = ParseValue(property.Value); } return result; } private dynamic ParseValue(JsonElement value) { return value.ValueKind switch { JsonValueKind.String => value.GetString()!, JsonValueKind.Number => value.TryGetInt32(out var intVal) ? intVal : value.GetDecimal(), JsonValueKind.True => true, JsonValueKind.False => false, JsonValueKind.Null => null!, JsonValueKind.Object => ParseJsonElement(value), JsonValueKind.Array => value.EnumerateArray().Select(ParseValue).ToList(), _ => value.ToString()! }; } public override void Write(Utf8JsonWriter writer, Dictionary<string, dynamic> value, JsonSerializerOptions options) { JsonSerializer.Serialize(writer, value, options); } }
- 注册转换器到System.Text.Json配置:
builder.Services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new DynamicDictionaryConverter()); });
方案3:轻量取值方案(无需修改序列化配置)
如果不想改动全局序列化规则,直接通过JsonElement自带的取值方法获取对应类型值即可,代码修改量最小:
string item01Id = incomingData["item01Id"].GetString(); int item01Value = incomingData["item01Value"].GetInt32(); string item02Id = incomingData["item02Id"].GetString(); string item02Value = incomingData["item02Value"].GetString();
注意:使用
dynamic作为参数类型会丢失编译时类型检查,存在运行时类型错误风险,若接口参数结构可预期,优先定义强类型DTO作为入参。
内容的提问来源于stack exchange,提问作者Glen Chia
相关产品推荐
相关产品推荐

