[CSHARP-1590] BsonObjectId type serializes as a discriminated type Created: 03/Mar/16  Updated: 05/Mar/16  Resolved: 05/Mar/16

Status: Closed
Project: C# Driver
Component/s: BSON, Serialization
Affects Version/s: 2.2.3
Fix Version/s: None

Type: Bug Priority: Minor - P4
Reporter: Julianna Peebles Assignee: Unassigned
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

When a BsonObjectId is stored in a field of type object, it is serialized as a discriminated type, rather than as an ObjectId type. The field is serialized with the ObjectSerializer, which does not check for the BsonObjectId type (or any other BsonValue type). One would intuitively expect BsonValue types to serialize to the corresponding BSON values, rather than as a discriminated type.

This can be reproduced by deserializing an ObjectId to a field of type object and then reserializing it to BSON. The result is a discriminated type document.



 Comments   
Comment by Julianna Peebles [ 04/Mar/16 ]

I looked more closely at our problematic code and realized what was actually happening is that the field of type object is populated using the _id from a RawBsonDocument. This causes the field to be serialized as a discriminated type. Apologies for my mistake.

Comment by Robert Stam [ 04/Mar/16 ]

The repro instructions aren't quite right. If you start with a document that has an ObjectId in it the ObjectId value will deserialize as an instance of ObjectId, not BsonObjectId, and if reserialized will not have a discriminator. For example, using this class:

public class C
{
    public object P { get; set; }
}

and this code:

var json = "{ P : ObjectId(\"0102030405060708090a0b0c\") }";
var c = BsonSerializer.Deserialize<C>(json);
 
json = c.ToJson();
Console.WriteLine(json);

The output is:

{ "P" : ObjectId("0102030405060708090a0b0c") }

Note: no discriminator was added.

This is more easily reproduced by creating an instance of BsonObjectId in code and serializing the class that contains it:

var c = new C { P = new BsonObjectId(new ObjectId("0102030405060708090a0b0c")) };
var json = c.ToJson();
Console.WriteLine(json);

which results in:

{ "P" : { "_t" : "MongoDB.Bson.BsonObjectId, MongoDB.Bson", "_v" : ObjectId("010
2030405060708090a0b0c") } }

Comment by Robert Stam [ 04/Mar/16 ]

The other side of the coin of serialization is deserialization. Sometimes we need a discriminator to tell the deserializer which exact type to instantiate during deserialization.

There are two ObjectId related classes in the .NET driver: MongoDB.Bson.ObjectId and MongoDB.Bson.BsonObjectId. The former is a struct (like Guid), and the latter is a part of the BsonValue family of classes that implement the BSON object model.

If you use an ObjectId it will serialize without a discriminator. But we have to add a discriminator to values of type BsonObjectId to differentiate them from ObjectId, otherwise the value would not round trip faithfully.

Comment by Craig Wilson [ 03/Mar/16 ]

Hi Julianna,

Could you provide some example code? There are many ways this could be done and I'm wondering about your exact situation.

Craig

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