[CSHARP-3023] ValueType properties should be deserializable from null if supported by their serializer Created: 23/Mar/20  Updated: 27/Oct/23  Resolved: 06/Apr/20

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

Type: Improvement Priority: Major - P3
Reporter: Vincent Kam (Inactive) Assignee: Robert Stam
Resolution: Works as Designed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified


 Description   

Per the contributor PR description:

Currently, if a struct/ValueType has its own converter registered it can be deserialized from null. However if the same struct/ValueType is property (or field) of a class, deserialization fails. Given that there is no test failing if I change that behaviour, I assume that it is a bug. Nevertheless, given example below, I think it makes sense to support it anyway.

https://github.com/mongodb/mongo-csharp-driver/pull/395



 Comments   
Comment by Robert Stam [ 06/Apr/20 ]

I don't think any changes are required in the driver. I used your example and after fixing two small issues the tests pass fine with no changes to the driver.

  1. The JSON string in the Deserialize_StructAsPropertyFromModel_DefaultValue test method used the wrong field name (should be "Number" instead of "Value"). I refactored the method to:

[Fact]
public void Deserialize_StructAsPropertyFromModel_DefaultValue()
{
    var address = BsonSerializer.Deserialize<Address>(@"{ ""Number"": null }");
    Assert.Equal(default, address.Number);
}

2. In your custom serializer you must "consume" the value from the reader even if you don't want to "read" it, otherwise the reader is still positioned at the value. I refactored HouseNumberSerializer.Deserialize to:

public override HouseNumber Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
    var bsonType = context.Reader.GetCurrentBsonType();
 
    if (bsonType == BsonType.Int32)
    {
        return new HouseNumber(context.Reader.ReadInt32());
    }
    else
    {
        context.Reader.SkipValue(); // if you choose not to read the value you must skip it
        return default;
    }
}

With those two changes the tests in your example pass without changes to the driver.

 

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