Search code examples
c#mongodbmongodb-.net-drivermongodb-csharp-2.0

Serialize mongodb document to domain object


I'm trying to read a mondodb document into my domain class (Company) but get an error on one of the properties. The error message reads:

"Expected a nested document representing the serialized form of a OrgNumber value, but found a value of type String instead"

The objects looks like this:

public class OrgNumber
{
    public string Value { get; private set; }
    ...

    private OrgNumber() { }

    public OrgNumber(string value) {
            Value = value;
    }
}

public class Company
{
    public string Name { get; private set; }
    public OrgNumber OrgNumber { get; private set; }
    ...

    private Company() { }

    public Company(string name, OrgNumber orgNumber)
    {
            Name = name;
            OrgNumber = orgNumber;
    }
}

The mongodb document looks like this:

{
"name": "Company name",
"orgNumber": "1234-5678",
}

I'm reading the document and mapping it directly into my domain model:

var collection = _mongoDb.GetCollection<Company>("Companies");
var result = await collection.Find(c => c.CompanyId == companyId).SingleOrDefaultAsync();

How do I correctly get the string representation of OrgNumber to the correct type OrgNumber?


Solution

  • You can create your own serializer inheriting from SerializerBase<T>

    public class OrgNumberSerializer : SerializerBase<OrgNumber>
    {
        public override OrgNumber Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
        {
            var serializer = BsonSerializer.LookupSerializer(typeof(string));
            var data = serializer.Deserialize(context, args);
            return new OrgNumber(data.ToString());
        }
    
        public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, OrgNumber value)
        {
            var serializer = BsonSerializer.LookupSerializer(typeof(string));
            serializer.Serialize(context, value.Value);
        }
    }
    

    Then it needs to be registered globally using below line:

    BsonSerializer.RegisterSerializer(typeof(OrgNumber), new OrgNumberSerializer());
    

    You can find more about the details here