含C# dynamic字段的模型写入MongoDB时抛出序列化异常
解决MongoDB序列化C# dynamic类型(JObject)的问题
问题核心
从Cosmos DB迁移到MongoDB时,使用InsertOneAsync()插入含dynamic属性的对象抛出序列化异常——原因是运行时dynamic实际为Newtonsoft.Json.Linq.JObject类型,而MongoDB默认序列化器未配置允许该类型序列化。
解决方案
方案1:替换dynamic为MongoDB原生BsonDocument类型
直接使用MongoDB的BsonDocument替代dynamic,这是最贴合MongoDB生态的方案,无需额外配置即可正常序列化。
修改模型类:
namespace Entities.Models { [BsonIgnoreExtraElements] public class UPModel { [JsonProperty(PropertyName = "_id")] [BsonId] [BsonRepresentation(BsonType.ObjectId)] public string BsonId { get; set; } = string.Empty; [BsonElement("resource")] public Resource Resource{ get; set; } [BsonElement("preference")] public Preference Preference { get; set; } } [BsonIgnoreExtraElements] public class Resource { [BsonElement("id")] public string Id { get; set; } [BsonElement("identifiers")] public BsonDocument Identifiers { get; set; } } [BsonIgnoreExtraElements] public class Preference { [BsonElement("id")] public string Id { get; set; } [BsonElement("value")] public BsonDocument Value { get; set; } } }
如果原有数据是JObject类型,可直接转换为BsonDocument:
// 假设originalIdentifiers是JObject实例 resource.Identifiers = BsonDocument.Parse(originalIdentifiers.ToString());
方案2:注册JObject自定义序列化器
通过自定义序列化器,让MongoDB支持JObject类型的序列化/反序列化。
- 实现JObject序列化器:
public class JObjectBsonSerializer : IBsonSerializer<JObject> { public Type ValueType => typeof(JObject); public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, JObject value) { var bsonDoc = BsonDocument.Parse(value.ToString()); BsonDocumentSerializer.Instance.Serialize(context, args, bsonDoc); } public JObject Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) { var bsonDoc = BsonDocumentSerializer.Instance.Deserialize(context, args); return JObject.Parse(bsonDoc.ToJson()); } }
- 在MongoDB客户端初始化前注册序列化器:
BsonSerializer.RegisterSerializer(typeof(JObject), new JObjectBsonSerializer()); // 后续正常初始化客户端和集合 var client = new MongoClient("your_connection_string"); var database = client.GetDatabase("your_db"); var _collection = database.GetCollection<UPModel>("your_collection");
方案3:转换为Dictionary<string, object>
将JObject转换为Dictionary<string, object>,MongoDB默认支持该类型的序列化。
修改模型属性类型:
[BsonElement("identifiers")] public Dictionary<string, object> Identifiers { get; set; } [BsonElement("value")] public Dictionary<string, object> Value { get; set; }
转换JObject为Dictionary:
// 假设originalValue是JObject实例 preference.Value = originalValue.ToObject<Dictionary<string, object>>();
内容的提问来源于stack exchange,提问作者Rishabh Nigam
相关产品推荐
相关产品推荐

