Search code examples
c#dapperjsonb

Does Dapper for Postgres (in C#) need a type mapper to map a List<T> to JSONB if the model itself (e.g. T) is already known?


Does Dapper need a type mapper to handle the following scenario.

Let's assume, the database (Postgres) has a column that is in JSONB: Events which in C# is a List<Event> with Event as simple as:

public sealed class Event
{
    public string Test { get; set; } = string.Empty;
}

If I add a generic JSON mapper to Dapper like this: SqlMapper.AddTypeHandler(new JsonMapper<Event>()); with the mapper itself using the following code:

public class JsonMapper<T> : SqlMapper.TypeHandler<T> where T : class, new()
{
    public override T Parse(object? value)
    {
        var config = new T();

        if (value is not null)
        {
            var stringValue = value.ToString() ?? string.Empty;
            config = JsonConvert.DeserializeObject<T>(stringValue, NewtonsoftJsonSerializerSettings);
        }

        return config ?? new();
    }

    public override void SetValue(IDbDataParameter parameter, T? value)
    {
        parameter.Value = JsonConvert.SerializeObject(value, NewtonsoftJsonSerializerSettings);
    }
    
    private static JsonSerializerSettings NewtonsoftJsonSerializerSettings = new()
    {
        TypeNameHandling = TypeNameHandling.All,
        NullValueHandling = NullValueHandling.Ignore,
        Formatting = Formatting.Indented,
        ObjectCreationHandling = ObjectCreationHandling.Replace,
        // Don't care about these, not relevant for the question
        //Converters = new List<JsonConverter> { new IsoDateTimeConverter(), new IpAddressConverter(), new IpEndpointConverter() }
    };
}

do I need to add SqlMapper.AddTypeHandler(new JsonMapper<List<Event>>()); as well or does Dapper get this implicitely somehow?


Solution

  • I have tested this now: You really have to add all type handlers for all types you want to map explicitely. So in my example, you would need SqlMapper.AddTypeHandler(new JsonMapper<Event>()); as well as SqlMapper.AddTypeHandler(new JsonMapper<List<Event>>());.