Skip to content

Commit d3f75f8

Browse files
authored
CSHARP-1485: Fix ExpandoObject serialization to permit nulls. (#542)
1 parent 46aac52 commit d3f75f8

File tree

2 files changed

+45
-2
lines changed

2 files changed

+45
-2
lines changed

src/MongoDB.Bson/Serialization/Serializers/DynamicDocumentBaseSerializer.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515

1616
using System;
1717
using System.Dynamic;
18-
using System.IO;
1918
using System.Linq.Expressions;
2019
using MongoDB.Bson.IO;
2120

@@ -25,7 +24,7 @@ namespace MongoDB.Bson.Serialization.Serializers
2524
/// Base serializer for dynamic types.
2625
/// </summary>
2726
/// <typeparam name="T">The dynamic type.</typeparam>
28-
public abstract class DynamicDocumentBaseSerializer<T> : SerializerBase<T> where T : IDynamicMetaObjectProvider
27+
public abstract class DynamicDocumentBaseSerializer<T> : SerializerBase<T> where T : class, IDynamicMetaObjectProvider
2928
{
3029
// private static fields
3130
private static readonly IBsonSerializer<object> _objectSerializer = BsonSerializer.LookupSerializer<object>();
@@ -65,6 +64,10 @@ public override T Deserialize(BsonDeserializationContext context, BsonDeserializ
6564
bsonReader.ReadEndDocument();
6665
return document;
6766

67+
case BsonType.Null:
68+
bsonReader.ReadNull();
69+
return null;
70+
6871
default:
6972
message = string.Format("Cannot deserialize a '{0}' from BsonType '{1}'.", BsonUtils.GetFriendlyTypeName(typeof(T)), bsonType);
7073
throw new FormatException(message);
@@ -81,6 +84,12 @@ public override void Serialize(BsonSerializationContext context, BsonSerializati
8184
{
8285
var bsonWriter = context.Writer;
8386

87+
if (value == null)
88+
{
89+
bsonWriter.WriteNull();
90+
return;
91+
}
92+
8493
var metaObject = value.GetMetaObject(Expression.Constant(value));
8594
var memberNames = metaObject.GetDynamicMemberNames();
8695
var dynamicContext = context.With(ConfigureSerializationContext);

tests/MongoDB.Bson.Tests/Serialization/Serializers/ExpandoObjectSerializerTests.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,40 @@ public void TestRoundTrip()
5151
Assert.True(bson.SequenceEqual((rehydrated).ToBson()));
5252
}
5353

54+
[Fact]
55+
public void TestNestedExpandoRoundTrip()
56+
{
57+
var document = new NestedExpando {Id = ObjectId.GenerateNewId(), ExtraData = new ExpandoObject()};
58+
59+
var json = document.ToJson();
60+
var expected = $"{{ \"_id\" : ObjectId(\"{document.Id}\"), \"ExtraData\" : {{ }} }}";
61+
Assert.Equal(expected, json);
62+
63+
var bson = document.ToBson();
64+
var rehydrated = BsonSerializer.Deserialize<NestedExpando>(bson);
65+
Assert.True(bson.SequenceEqual(rehydrated.ToBson()));
66+
}
67+
68+
[Fact]
69+
public void TestNullNestedExpandoRoundTrip()
70+
{
71+
var document = new NestedExpando {Id = ObjectId.GenerateNewId(), ExtraData = null};
72+
73+
var json = document.ToJson();
74+
var expected = $"{{ \"_id\" : ObjectId(\"{document.Id}\"), \"ExtraData\" : null }}";
75+
Assert.Equal(expected, json);
76+
77+
var bson = document.ToBson();
78+
var rehydrated = BsonSerializer.Deserialize<NestedExpando>(bson);
79+
Assert.True(bson.SequenceEqual(rehydrated.ToBson()));
80+
}
81+
82+
class NestedExpando
83+
{
84+
public ObjectId Id { get; set; }
85+
public ExpandoObject ExtraData { get; set; }
86+
}
87+
5488
#if NET452
5589
[Fact]
5690
public void TestDeserializingDiscriminatedVersion()

0 commit comments

Comments
 (0)