c# - 如何为字典中的值创建自定义序列化程序?
问题描述
我有以下课程:
public class Farm
{
public string County {get;set;}
public Dictionary<string, object> FarmItems {get;set;}
}
我需要实现一个自定义序列化器/反序列化器,如果它是值中的整数,则将其作为字符串存储在数据库中,然后将其反序列化回整数
我查看了文档,他们详细说明了如何为单个值而不是字典https://mongodb.github.io/mongo-csharp-driver/2.12/reference/bson/serialization/
此外,文档没有提到如何实现它,我只是在创建我的类之后添加一个属性,如下所示:
[BsonSerializer(typeof(MyCustomSerializer))]
public Dictionary<string, object> FarmItems {get;set;}
解决方案
干得好:
public class MyDictionarySerialzer : SerializerBase<Dictionary<string, object>>
{
public override void Serialize(BsonSerializationContext ctx, BsonSerializationArgs args, Dictionary<string, object> dictionary)
{
if (dictionary == null)
{
ctx.Writer.WriteStartArray();
ctx.Writer.WriteEndArray();
return;
}
ctx.Writer.WriteStartArray();
foreach (var kvPair in dictionary)
{
ctx.Writer.WriteStartDocument();
ctx.Writer.WriteName("k");
ctx.Writer.WriteString(kvPair.Key);
ctx.Writer.WriteName("v");
if (kvPair.Value is int)
ctx.Writer.WriteString(kvPair.Value.ToString());
else
BsonSerializer.Serialize(ctx.Writer, kvPair.Value);
ctx.Writer.WriteEndDocument();
}
ctx.Writer.WriteEndArray();
}
public override Dictionary<string, object> Deserialize(BsonDeserializationContext ctx, BsonDeserializationArgs args)
{
Dictionary<string, object> dict = new();
switch (ctx.Reader.CurrentBsonType)
{
case BsonType.Array:
foreach (var val in BsonSerializer.Deserialize<BsonArray>(ctx.Reader))
{
string key = val["k"].AsString;
object value = BsonSerializer.Deserialize<object>(val["v"].ToJson());
if (int.TryParse(value?.ToString(), out var parsedInt))
value = parsedInt;
dict.Add(key, value);
}
return dict;
default:
throw new BsonSerializationException("Unable to deserialize dictionary!");
}
}
}
如果您在字典值中存储任何复杂实体,则必须像这样使用 mongo 驱动程序注册(在应用程序启动时)该复杂类型(否则反序列化将失败):
BsonClassMap.RegisterClassMap<ComplexItem>();
像这样简单地装饰属性:
public class Farm
{
[BsonSerializer(typeof(MyDictionarySerialzer))]
public Dictionary<string, object> FarmItems { get; set; }
}
示例实体:
var example = new Farm
{
FarmItems = new Dictionary<string, object>()
{
{"empty",null },
{"string","test string" },
{"int",100 },
{"complex",new ComplexItem{ Age = 10, Name = "test" } }
}
};
它将像这样序列化到数据库:
{
"FarmItems" : [
{
"k" : "empty",
"v" : null
},
{
"k" : "string",
"v" : "test string"
},
{
"k" : "int",
"v" : "100"
},
{
"k" : "complex",
"v" : {
"_t" : "ComplexItem",
"Name" : "test",
"Age" : 10
}
}
]
}
推荐阅读
- php - 如何创建一个使用多行数据的表单?
- java - 如何在javafx中堆叠形状
- laravel - Laravel livewire - 检查复选框是否被选中
- html - 在 div 中添加容器不会将容器与中心对齐,以及如何在保持初始大小的同时获得滚动效果
- google-apps-script - 将代码从删除修改为清除内容 - Google Sheets Apps 脚本
- c# - 具有从嵌套集合中的项目动态创建的列的 DataGrid
- javascript - 如何根据第二个数组中的值将多个元素添加到数组 X 次?
- r - Purrr 将索引数据帧与数据帧相乘
- python - Python嵌套字典到熊猫df
- node.js - 有没有办法在 Node.js 中使用 ksqldb 表(推送查询)?