总之,您的模型上有一个公共的字符串属性,其中包含JSON,您希望通过将JSON字符串反序列化为一些中间
DTO,然后将DTO本身序列化到MongoDB中来内部序列化它。
以下是解决您问题的几种方法。
首先,您可以在数据模型中引入一个私有的DTO值属性
Dob SerializedDOB { get; set; }
,将该属性标记为
[BsonElement("dob")]
以强制进行序列化,然后修改
dob
为一个非序列化代理属性,在其getter和setter中从底层的
SerializedDOB
进行序列化和反序列化。以下代码显示了这种方法:
public class Person
{
public string name { get; set; }
[BsonIgnore]
public string dob
{
get => BsonExtensionMethods.ToJson(SerializedDOB);
set => SerializedDOB = MyBsonExtensionMethods.FromJson<Dob>(value);
}
[BsonElement("dob")]
Dob SerializedDOB { get; set; }
class Dob
{
public string month { get; set; }
public int day { get; set; }
public int year { get; set; }
}
}
这种方法的优点在于,通过将JSON字符串作为代理,设置程序自动确保其格式正确。
演示fiddle #1
在此处。
其次,您可以为
dob
创建一个自定义{{link2:
SerializerBase<string>
}},在(反)序列化期间将字符串值映射到DTO
Dob
。以下代码显示了此方法:
public class Person
{
public string name { get; set; }
[BsonSerializer(typeof(JsonStringAsObjectSerializer<Dob>))]
public string dob { get; set; }
class Dob
{
public string month { get; set; }
public int day { get; set; }
public int year { get; set; }
}
}
public class JsonStringAsObjectSerializer<TObject> : SerializerBase<string> where TObject : class
{
public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, string value)
{
if (value == null)
{
var bsonWriter = context.Writer;
bsonWriter.WriteNull();
}
else
{
var obj = MyBsonExtensionMethods.FromJson<TObject>(value);
var serializer = BsonSerializer.LookupSerializer(typeof(TObject));
serializer.Serialize(context, obj);
}
}
public override string Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
var bsonReader = context.Reader;
var serializer = BsonSerializer.LookupSerializer(typeof(TObject));
var obj = (TObject)serializer.Deserialize(context);
return (obj == null ? null : BsonExtensionMethods.ToJson(obj));
}
}
这种方法的优点是可以在需要时重复使用
JsonStringAsObjectSerializer<TObject>
。
演示fiddle #2
这里。
以下扩展方法与两个解决方案一起使用,将JSON字符串反序列化为指定类型,因为令人困惑的是,
BsonExtensionMethods
有一个
ToJson()
方法,但没有
FromJson()
方法:
public static partial class MyBsonExtensionMethods
{
public static TNominalType FromJson<TNominalType>(
string json,
JsonReaderSettings readerSettings = null,
IBsonSerializer<TNominalType> serializer = null,
Action<BsonDeserializationContext.Builder> configurator = null)
{
return (TNominalType)FromJson(json, typeof(TNominalType), readerSettings, serializer, configurator);
}
public static object FromJson(
string json,
Type nominalType,
JsonReaderSettings readerSettings = null,
IBsonSerializer serializer = null,
Action<BsonDeserializationContext.Builder> configurator = null)
{
if (nominalType == null || json == null)
throw new ArgumentNullException();
serializer = serializer ?? BsonSerializer.LookupSerializer(nominalType);
if (serializer.ValueType != nominalType)
throw new ArgumentException(string.Format("serializer.ValueType {0} != nominalType {1}.", serializer.GetType().FullName, nominalType.FullName), "serializer");
using (var textReader = new StringReader(json))
using (var reader = new JsonReader(textReader, readerSettings ?? JsonReaderSettings.Defaults))
{
var context = BsonDeserializationContext.CreateRoot(reader, configurator);
return serializer.Deserialize(context);
}
}
}