[CSHARP-4056] GUID in BsonDocument ignores registered GuidSerializer Created: 14/Feb/22  Updated: 27/Oct/23  Resolved: 14/Feb/22

Status: Closed
Project: C# Driver
Component/s: Serialization
Affects Version/s: 2.14.1
Fix Version/s: None

Type: Bug Priority: Unknown
Reporter: James Kovacs Assignee: James Kovacs
Resolution: Works as Designed Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

If you register a GuidSerializer, this serializer is respected for POCOs, but ignored for BsonDocuments.

using System;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;
using MongoDB.Driver;
 
BsonSerializer.RegisterSerializer(new GuidSerializer(GuidRepresentation.Standard));
 
var client = new MongoClient();
var db = client.GetDatabase("test");
var collAsItem = db.GetCollection<Item>("guids");
var collAsBson = db.GetCollection<BsonDocument>("guids");
 
collAsBson.DeleteMany("{}");
 
collAsItem.InsertOne(new Item {
    Id = Guid.NewGuid(),
    Name = "AsOrder"
});
 
collAsBson.InsertOne(new BsonDocument {{ "_id", Guid.NewGuid() }, { "Name", "AsBson"}});
 
var docs = collAsBson.AsQueryable().ToList();
foreach (var doc in docs)
{
    Console.WriteLine($"{doc["_id"]} ({doc["Name"]})");
}
 
class Item
{
    public Guid Id { get; set; }
    public string Name { get; set; }
}

The output is as follows:

UuidStandard:0xb9d8bcca00d04b33b2d8bde43b07818e (AsOrder)
UuidLegacy:0x12000db290a3c242b855358edade519b (AsBson)

If we configure the default GUID representation (whether or not the GuidSerializer above is registered), we get the correct output:

BsonDefaults.GuidRepresentation = GuidRepresentation.Standard;

Output:

UuidStandard:0x1e343d0ea60f4e06b463ea0d6d24840f (AsOrder)
UuidStandard:0x1b0ad1052a4947688e35d39ab2515b88 (AsBson)



 Comments   
Comment by James Kovacs [ 14/Feb/22 ]

I neglected to read the compiler warnings of my repro, which clearly state:

/Users/james/Dropbox/code/cases/csharp4056/Program.cs(27,49): warning CS1062: The best overloaded Add method 'BsonValue.implicit operator BsonValue(Guid)' for the collection initializer element is obsolete. Use the BsonBinaryData constructor instead and specify a Guid representation. [/Users/james/Dropbox/code/cases/csharp4056/csharp4056.csproj]
    1 Warning(s)
    0 Error(s)

BsonValue serialization is completely deterministic and does not rely on the SerializerRegistry. This is why registering a default serializer for GUIDs does not affect the serialization for a GUID contained in a BsonDocument.

When a GUID is included in a BsonDocument, we are relying on an implicit conversion from System.Guid to BsonValue. This implicit conversion does not allow specification of the GuidRepresentation. The correct way to add a GUID to a BsonDocument is:

var doc = new BsonDocument {{ "_id", new BsonBinaryData(Guid.NewGuid(), GuidRepresentation.Standard) }};

Use the BsonBinaryData(Guid, GuidRepresentation) constructor when adding GUIDs directly to BsonDocuments.

Note: You must opt into GuidRepresentationMode.V3 in order to set the GuidRepresentation on a per-field basis. See GuidRepresentationMode for more information.

Generated at Wed Feb 07 21:47:05 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.