mongodb-csharp


How to force serialization of decimal values inside dictionaries as doubles in mongodb csharp driver?


I have the following dictionary:
var dict = new Dictionary<string, object> {
{ "decimal", 3.503m },
{ "int", 45 }
};
var serializedString = dict.ToJson();
By default that is serialized as:
{ "decimal" : { "_t" : "System.Decimal", "_v" : "3.503" }, "int" : 45 }
If I override DecimalSerializer as:
BsonSerializer.RegisterSerializer<decimal>(new DecimalSerializer().WithRepresentation(BsonType.Double));
That only influences on how "_v" value is serialized, e.g.:
{ "decimal" : { "_t" : "System.Decimal", "_v" : 3.503 }, "int" : 45 }
Expected result:
{ "decimal" : 3.503, "int" : 45 }
Please advise
The cause of the .Net types in the bson, is the lack of type in the dictionary. The Bson serializers are trying to get enough state to restore the original object of the items in the dictionary. From the context (the dictionary) they are of type "object", so the .Net type is inserted to know enough when deserializing.
The following solutions answer your question but lose the type information for deserializing.
Solution 1: Change the dictionary type to <string, decimal>
var dict = new Dictionary<string, decimal> {
{ "decimal", 3.503m },
{ "int", 45 }
};
var serializedString = dict.ToJson();
Results in: { "decimal" : "3.503", "int" : "45" }
With your override of the decimal serializer, you get the expected result.
{ "decimal" : 3.503, "int" : 45 }
Solution 2: Change the dictionary type to <string, double>
var dict = new Dictionary<string, double> {
{ "decimal", (double)3.503m },
{ "int", 45 }
};
var serializedString = dict.ToJson();
Results in the expected result: { "decimal" : 3.503, "int" : 45 }
Solution 3: Use custom serializer
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;
}
}
As another option, it's possible to override object serializer
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());
that still will not work for Hashtables.
Possible workaround for Hashtables:
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));

Related Links

Using a Regex against a simple list with `ElemMatch` in MongoDB .NET
projection wont work in mongodb c# driver
BsonClassMapSerializer already registered for AbstractClassSerializer
MongoDb C# Driver 2.0 Coalesce (or equivalent)?
MongoDB dynamic update of collection when changes occurs in another collection
MongoDB C# 2.0 TimeoutException
MongoDB C# 2.0 upgrade
Searching a MongoDB collection from the end (c#)
Handle extra elements outside of deserialized class
ASP.NET 5 with MongoDB
Store same fields twice during serialization
BsonDefaultValue set to empty list
Don't overwrite extra fields when serializing BSON?
MongoDB C# - how to save arbitrary JSON document as dynamic type?
mondodb linq query fails - is it mongodb driver or linq
New (2.6) $cond Aggregation Framework with c#?

Categories

HOME
redux-form
numbers
sh
google-cloud-datalab
jax-ws
jtextpane
lanczos
performancepoint
mql5
plist
opengl-es-3.0
datastage
shared-libraries
mapstruct
shortest-path
topology
windows-xp
visual-studio-extensions
exit
xunit
google-cloud-print
mat
android-things
tpm
recurring-events
memory-address
linkedhashmap
hreflang
contacts
openwhisk
least-squares
engine.io
trigonometry
watchface
x++
jide
dynamic-linq
dbcontext
vugen
x-ray
oracleclient
git-flow
skin
type-theory
offline.js
reachability
vorpal.js
lean
database-relations
user-management
jdi
sapscript
keyup
dnssec
canvg
nsurlsessiondatatask
jquery-forms-plugin
phpldapadmin
bcache
mass-assignment
dbaccess
nodelist
uncaught-typeerror
sip-server
sonarqube-5.0
deform
wcm
functional-java
ray
dot42
file-not-found
fpdi
gae-quotas
mt4j
model-driven-development
jeromq
hidapi
cffile
resource-management
booksleeve
pdfviewer
redis-py
azman
kqueue
isa-swizzling
agility.js
filemerge
mysql-error-1205
mbeans
uipagecontrol
ruby-1.8
todos

Resources

Database Users
RDBMS discuss
Database Dev&Adm
javascript
java
csharp
php
android
javascript
java
csharp
php
python
android
jquery
ruby
ios
html
Mobile App
Mobile App
Mobile App