Asp.net Core接收DTO动态JSON属性存入MongoDb出现JsonValueKind异常
问题原因
ASP.NET Core 默认使用 System.Text.Json 作为请求体的序列化/反序列化组件,当你将 DTO 中的 Content 字段声明为 dynamic 或无类型的 object 时,System.Text.Json 不会将其反序列化为匹配JSON结构的动态对象,而是会解析为 System.Text.Json.JsonElement 类型的实例。
你直接将 JsonElement 实例赋值给 object 类型变量后,MongoDB C# 驱动无法识别该类型,序列化时错误提取了 JsonElement 下的 ValueKind 枚举属性作为整个对象存入数据库,你看到的存储结果中的_v:1 就是JsonValueKind.Object对应的枚举值。
解决方案
方案1:替换默认序列化器为Newtonsoft.Json(最省心)
Newtonsoft.Json对dynamic类型的反序列化逻辑和MongoDB驱动的兼容性更好,操作步骤:
- 安装对应版本的NuGet包:
Install-Package Microsoft.AspNetCore.Mvc.NewtonsoftJson - 在服务注册逻辑中启用Newtonsoft.Json作为控制器的序列化器:
.NET 6+ 版本在Program.cs中修改:
builder.Services.AddControllers().AddNewtonsoftJson();
.NET 5及更早版本在Startup.cs的ConfigureServices方法中修改:
services.AddControllers().AddNewtonsoftJson();
配置完成后,dynamic? Content会被反序列化为Newtonsoft.Json.Linq.JObject实例,直接赋值给object存入MongoDB即可得到正确的结构。
方案2:保留System.Text.Json,手动转换类型
如果不想更换默认序列化器,可以做如下调整:
- 将DTO中的
Content类型显式声明为JsonElement?:
public class DocumentPostDTO { public string Path { get; set; } public JsonElement? Content { get; set; } }
- 存入MongoDB前手动转换为可识别的类型:
- 方式A:直接转为Bson结构存入
using MongoDB.Bson; // 直接读取JsonElement的原始JSON文本,转为BsonDocument BsonDocument content = BsonDocument.Parse(documentDto.Content.GetRawText());
- 方式B:转为标准动态对象
using System.Text.Json; // 反序列化为ExpandoObject动态对象 object _content = JsonSerializer.Deserialize<ExpandoObject>(documentDto.Content.GetRawText());
转换后再存入MongoDB即可得到正确的结构。
内容的提问来源于stack exchange,提问作者Deivydas Voroneckis
相关产品推荐
相关产品推荐

