diff --git a/src/MongoDB.Bson/Serialization/BsonClassMap.cs b/src/MongoDB.Bson/Serialization/BsonClassMap.cs index 87239a33bf5..e7410ef9031 100644 --- a/src/MongoDB.Bson/Serialization/BsonClassMap.cs +++ b/src/MongoDB.Bson/Serialization/BsonClassMap.cs @@ -1057,7 +1057,7 @@ public void Reset() _creatorMaps.Clear(); _creator = null; _declaredMemberMaps = new List(); - _discriminator = _classType.Name; + _discriminator = BsonUtils.GetFriendlyTypeName(_classType); _discriminatorIsRequired = false; _extraElementsMemberMap = null; _idMemberMap = null; diff --git a/tests/MongoDB.Bson.Tests/Jira/CSharp515Tests.cs b/tests/MongoDB.Bson.Tests/Jira/CSharp515Tests.cs index 27de1f7abaa..04350931f01 100644 --- a/tests/MongoDB.Bson.Tests/Jira/CSharp515Tests.cs +++ b/tests/MongoDB.Bson.Tests/Jira/CSharp515Tests.cs @@ -45,7 +45,7 @@ public S(IList list) } private static readonly string __discriminatorAssemblyName = "MongoDB.Bson.Tests"; - private string _jsonTemplate = ("{ '_id' : 1, 'R' : #V, 'S' : #V, 'RS' : { '_t' : 'S`1', '_v' : #V }, 'OR' : { '_t' : 'System.Collections.ObjectModel.ReadOnlyCollection`1[System.Int32]', '_v' : #V }, 'OS' : { '_t' : 'MongoDB.Bson.Tests.Jira.CSharp515.CSharp515Tests+S`1[System.Int32], " + __discriminatorAssemblyName + "', '_v' : #V } }").Replace("'", "\""); + private string _jsonTemplate = ("{ '_id' : 1, 'R' : #V, 'S' : #V, 'RS' : { '_t' : 'S', '_v' : #V }, 'OR' : { '_t' : 'System.Collections.ObjectModel.ReadOnlyCollection`1[System.Int32]', '_v' : #V }, 'OS' : { '_t' : 'MongoDB.Bson.Tests.Jira.CSharp515.CSharp515Tests+S`1[System.Int32], " + __discriminatorAssemblyName + "', '_v' : #V } }").Replace("'", "\""); [Fact] public void TestNull() diff --git a/tests/MongoDB.Bson.Tests/Serialization/Serializers/DiscriminatorTests.cs b/tests/MongoDB.Bson.Tests/Serialization/Serializers/DiscriminatorTests.cs index 78fe458a3aa..def1a5e027b 100644 --- a/tests/MongoDB.Bson.Tests/Serialization/Serializers/DiscriminatorTests.cs +++ b/tests/MongoDB.Bson.Tests/Serialization/Serializers/DiscriminatorTests.cs @@ -13,7 +13,9 @@ * limitations under the License. */ +using System.Collections.Generic; using System.Linq; +using FluentAssertions; using MongoDB.Bson.Serialization; using MongoDB.Bson.Serialization.Attributes; using MongoDB.Bson.TestHelpers; @@ -65,6 +67,79 @@ private class H : G { } + // BaseDocument and derived classes are used for tests with generic types + // It's necessary to specify the derived specific types with BsonKnownTypes for the deserialization to work. + [BsonKnownTypes(typeof(DerivedDocument))] + [BsonKnownTypes(typeof(DerivedDocument>>))] + [BsonKnownTypes(typeof(DerivedDocumentDouble))] + abstract class BaseDocument; + + class DerivedDocument : BaseDocument + { + [BsonId] + public int Id { get; set; } + + public T Value { get; set; } + } + + class DerivedDocumentDouble : BaseDocument + { + [BsonId] + public int Id { get; set; } + + public T1 Value1 { get; set; } + + public T2 Value2 { get; set; } + } + + [Fact] + public void TestDeserializeGenericType() + { + var serialized = """{ "_t" : "DerivedDocument", "_id" : 1, "Value" : 42 }"""; + var rehydrated = BsonSerializer.Deserialize(serialized); + rehydrated.Should().BeOfType>(); + } + + [Fact] + public void TestDeserializeGenericTypeWithNestedType() + { + var serialized = """{ "_t" : "DerivedDocument>>", "_id" : 1, "Value" : [{ "key" : 1 }] }"""; + var rehydrated = BsonSerializer.Deserialize(serialized); + rehydrated.Should().BeOfType>>>(); + } + + [Fact] + public void TestDeserializeGenericTypeWithTwoTypes() + { + var serialized = """{ "_t" : "DerivedDocumentDouble", "_id" : 1, "Value1" : 42, "Value2" : "hello" }"""; + var rehydrated = BsonSerializer.Deserialize(serialized); + rehydrated.Should().BeOfType>(); + } + + [Fact] + public void TestSerializeGenericType() + { + var document = new DerivedDocument { Id = 1, Value = 42 }; + var serialized = document.ToJson(typeof(BaseDocument)); + serialized.Should().Be("""{ "_t" : "DerivedDocument", "_id" : 1, "Value" : 42 }"""); + } + + [Fact] + public void TestSerializeGenericTypeWithNestedType() + { + var document = new DerivedDocument>> { Id = 1, Value = [new() { { "key", 1 } }] }; + var serialized = document.ToJson(typeof(BaseDocument)); + serialized.Should().Be("""{ "_t" : "DerivedDocument>>", "_id" : 1, "Value" : [{ "key" : 1 }] }"""); + } + + [Fact] + public void TestSerializeGenericTypeWithTwoTypes() + { + var document = new DerivedDocumentDouble { Id = 1, Value1 = 42, Value2 = "hello"}; + var serialized = document.ToJson(typeof(BaseDocument)); + serialized.Should().Be("""{ "_t" : "DerivedDocumentDouble", "_id" : 1, "Value1" : 42, "Value2" : "hello" }"""); + } + [Fact] public void TestSerializeObjectasObject() {