C# MongoDB驱动如何实现多类型Value字段的序列化与反序列化
MongoDB C#驱动多类型Value字段序列化解决方案
方案1:直接兼容多类型Value(无需转换存储格式)
你遇到的报错原因是Value属性定义为Dictionary<string, object>,仅能对应BSON的Document类型,遇到布尔、字符串等其他BSON类型就会反序列化失败。最简单的解决方法是将Value的类型改为MongoDB驱动提供的BsonValue类型:
class MyFieldValue { public string FieldName { get; set; } // BsonValue兼容所有BSON类型,支持null、布尔、字符串、对象、数组等 public BsonValue Value { get; set; } }
使用时可以通过内置属性判断类型再取值:
// 取值示例 var fieldValue = data.FieldValue; if (fieldValue.Value.IsBoolean) { bool boolValue = fieldValue.Value.AsBoolean; } else if (fieldValue.Value.IsString) { string strValue = fieldValue.Value.AsString; } else if (fieldValue.Value.IsBsonDocument) { // 转为字典 Dictionary<string, object> dict = fieldValue.Value.AsBsonDocument.ToDictionary(); }
如果你不想在业务代码里引入BsonValue类型,可以通过自定义序列化器实现原生Dictionary<string, object>类型兼容多类型值:
public class MultiTypeValueSerializer : SerialerBase<Dictionary<string, object>> { public override Dictionary<string, object> Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) { var reader = context.Reader; var currentType = reader.GetCurrentBsonType(); // 处理非对象类型 return currentType switch { BsonType.Boolean => new Dictionary<string, object> { ["value"] = reader.ReadBoolean() }, BsonType.String => new Dictionary<string, object> { ["value"] = reader.ReadString() }, BsonType.Null => { reader.ReadNull(); return null; }, BsonType.Document => BsonSerializer.Deserialize<BsonDocument>(reader).ToDictionary(), _ => throw new NotSupportedException($"不支持的BSON类型:{currentType}") }; } public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Dictionary<string, object> value) { // 如果是单value键的包装字典,直接序列化原始值 if (value != null && value.Count == 1 && value.TryGetValue("value", out var rawValue)) { BsonSerializer.Serialize(context.Writer, rawValue); return; } // 正常序列化字典为BSON文档 BsonSerializer.Serialize(context.Writer, value.ToBsonDocument()); } }
给Value属性指定序列化器即可:
class MyFieldValue { public string FieldName { get; set; } [BsonSerializer(typeof(MultiTypeValueSerializer))] public Dictionary<string, object> Value { get; set; } }
方案2:统一转换为字典格式存储
如果需要所有Value存储时都统一为{"value": xxx}的对象格式,只需修改上面自定义序列化器的Serialize方法,所有值都包装为带value键的BSON文档即可:
public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, Dictionary<string, object> value) { BsonDocument doc; if (value == null) { doc = new BsonDocument("value", BsonNull.Value); } // 非包装格式的多键对象直接保留原有结构 else if (value.Count != 1 || !value.ContainsKey("value")) { doc = value.ToBsonDocument(); } // 单值包装成value键对象 else { doc = new BsonDocument("value", BsonValue.Create(value["value"])); } BsonSerializer.Serialize(context.Writer, doc); }
这个方案下不管写入的是布尔、字符串还是复杂对象,MongoDB中存储的Value字段始终是对象类型,不会出现类型不匹配的反序列化报错。
内容的提问来源于stack exchange,提问作者egeo
相关产品推荐
相关产品推荐

