【问题标题】:How to force serialization of decimal values inside dictionaries as doubles in mongodb csharp driver?如何在 mongodb csharp 驱动程序中强制将字典中的十进制值序列化为双精度值?
【发布时间】:2016-04-08 02:29:37
【问题描述】:

我有以下字典:

var dict = new Dictionary<string, object> {
  { "decimal", 3.503m },
  { "int", 45 }
};
var serializedString = dict.ToJson();

默认序列化为:

{ "decimal" : { "_t" : "System.Decimal", "_v" : "3.503" }, "int" : 45 } 

如果我将 DecimalSerializer 覆盖为:

BsonSerializer.RegisterSerializer<decimal>(new DecimalSerializer().WithRepresentation(BsonType.Double));

这只影响“_v”值如何序列化,例如:

{ "decimal" : { "_t" : "System.Decimal", "_v" : 3.503 }, "int" : 45 } 

预期结果:

{ "decimal" : 3.503, "int" : 45 } 

请指教

【问题讨论】:

标签: mongodb-.net-driver mongodb-csharp-2.0


【解决方案1】:

bson 中 .Net 类型的原因是字典中缺少类型。 Bson 序列化程序试图获得足够的状态来恢复字典中项目的原始对象。从上下文(字典)来看,它们属于“对象”类型,因此在反序列化时插入了 .Net 类型以了解足够多的信息。

以下解决方案回答了您的问题,但会丢失反序列化的类型信息

解决方案1:将字典类型更改为&lt;string, decimal&gt;

var dict = new Dictionary<string, decimal> {
  { "decimal", 3.503m },
  { "int", 45 }
};
var serializedString = dict.ToJson();

结果:{ "decimal" : "3.503", "int" : "45" }

通过覆盖十进制序列化程序,您会得到预期的结果。

{ "decimal" : 3.503, "int" : 45 }

解决方案2:将字典类型更改为&lt;string, double&gt;

var dict = new Dictionary<string, double> {
  { "decimal", (double)3.503m },
  { "int", 45 }
};
var serializedString = dict.ToJson();

得到预期结果:{ "decimal" : 3.503, "int" : 45 }

解决方案 3:使用自定义序列化程序

public class MyDictionarySerializer : SerializerBase<Dictionary<string, object>>
{
  public override void Serialize(MongoDB.Bson.Serialization.BsonSerializationContext context, MongoDB.Bson.Serialization.BsonSerializationArgs args, Dictionary<string, object> dictionary)
  {
    context.Writer.WriteStartArray();
    foreach (var item in dictionary)
    {
      context.Writer.WriteStartDocument();
      context.Writer.WriteString(item.Key);

      // TODO your converstions from object to double
      var value = (double)item.Value;

      context.Writer.WriteDouble(value);
      context.Writer.WriteEndDocument();
    }
    context.Writer.WriteEndArray();
  }

  public override Dictionary<string, object> Deserialize(MongoDB.Bson.Serialization.BsonDeserializationContext context, MongoDB.Bson.Serialization.BsonDeserializationArgs args)
  {
    context.Reader.ReadStartArray();

    var result = new Dictionary<string, object>();
    while (true)
    {
      try
      {
        //this catch block only need to identify the end of the Array
        context.Reader.ReadStartDocument();
      }
      catch (Exception exp)
      {
        context.Reader.ReadEndArray();
        break;
      }

      var key = context.Reader.ReadString();
      double value = context.Reader.ReadDouble();
      result.Add(key, value);

      context.Reader.ReadEndDocument();
    }
    return result;
  }
}

【讨论】:

  • 感谢您提供建议的选项。是的,我知道我会丢失类型信息,这就是我想要实现的。我需要以与双精度相同的方式处理小数(并反序列化为双精度)。除了建议的选项之外,我想我还可以迭代我的字典并首先将所有十进制值转换为双精度值,然后调用默认的序列化程序,这将产生所需的结果。但是,一旦序列化程序在执行过程中迭代同一个字典,我认为有更标准的方法可以覆盖该行为并防止在我的字典中预先转换值?
【解决方案2】:

作为另一种选择,可以覆盖对象序列化器

public class DecimalsOverridingObjectSerializer : ObjectSerializer
{
    public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value) {
        if (value != null && value is decimal) {
            base.Serialize(context, args, Convert.ToDouble(value));
        } else {
            base.Serialize(context, args, value);
        }
    }
}
BsonSerializer.RegisterSerializer(typeof(object), new DecimalsOverridingObjectSerializer());

这仍然不适用于哈希表。 哈希表的可能解决方法:

public class DecimalsOverridingDictionarySerializer<TDictionary>: 
    DictionaryInterfaceImplementerSerializer<TDictionary>
    where TDictionary : class, IDictionary, new()
{
    public DecimalsOverridingDictionarySerializer(DictionaryRepresentation dictionaryRepresentation)
           : base(dictionaryRepresentation, new DecimalsOverridingObjectSerializer(), new DecimalsOverridingObjectSerializer())
    {   }

}
BsonSerializer.RegisterSerializer(typeof(Hashtable), new DecimalsOverridingDictionarySerializer<Hashtable>(DictionaryRepresentation.Document));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-16
    • 2020-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多