Override the default serializers for BsonTypes

11 views
Skip to first unread message

Matthew James Davis

unread,
May 27, 2017, 6:35:34 PM5/27/17
to mongodb-user
See my StackOverflow question here for background: https://stackoverflow.com/questions/44085267/mongo-c-sharp-driver-and-objectid-json-string-format-in-net-core.

The core is that if I parse the following JSON as a BsonDocument, I can't get it back into this form without doing a ton of extra boiler plate work:

{
  _id
: 'abc123'
}

You cannot override any of the BsonValue derived types:

BsonSerializer.RegisterSerializer(new BsonObjectIdSerializer());
// Throws error:
// MongoDB.Bson.BsonSerializationException: A serializer cannot be registered for type BsonObjectId because it is a subclass of BsonValue.


The default JsonWriter class has no extensibility point: https://github.com/mongodb/mongo-csharp-driver/blob/2894c3df1cf155a793aa8641cbc6cdb6cf308a7a/src/MongoDB.Bson/IO/JsonWriter.cs#L486

/// <summary>
/// Writes a BSON ObjectId to the writer.
/// </summary>
/// <param name="objectId">The ObjectId.</param>
public override void WriteObjectId(ObjectId objectId)
{
   
if (Disposed) { throw new ObjectDisposedException("JsonWriter"); }
   
if (State != BsonWriterState.Value && State != BsonWriterState.Initial)
   
{
       
ThrowInvalidState("WriteObjectId", BsonWriterState.Value, BsonWriterState.Initial);
   
}


   
WriteNameHelper(Name);
   
switch (_jsonWriterSettings.OutputMode)
   
{
       
case JsonOutputMode.Strict:
            _textWriter
.Write("{{ \"$oid\" : \"{0}\" }}", objectId.ToString());
           
break;


       
case JsonOutputMode.Shell:
       
default:
            _textWriter
.Write("ObjectId(\"{0}\")", objectId.ToString());
           
break;
   
}


   
State = GetNextState();
}

If this is all there is at the moment and I'm not missing something that will accomplish the desired behavior, then I'd like to propose two options:

(a) Let's change the default text writer. I'm not sure why anyone would want to pass around $oid or $date objects in json. ObjectIds are easily represented as strings, and dates are typically represented in the well defined JavaScript `toISOString()` format: "2017-05-27T10:59:49.955Z".

(b) Let's add some sort of extensibility hook that allows for overwriting this default behavior. The BsonSerializer approach is tough because it depends on the Writer type, which I think is a good idea, but it takes away all the power and flexibility a developer might need in this use case. Furthermore it's simply disabled for the most important types.

Let me know thoughts! Also, please answer my question on StackOverflow if there is a better, supported way.

Thanks
Matt Davis
Reply all
Reply to author
Forward
0 new messages