Search code examples
c#json.netautomapperautomapper-6

How to prevent AutoMapper from initializing destination JObject member when source is null


Suppose you have the following classes:

public class Source
{
    public string Data { get; set; }
}

public class Destination
{
    public JObject Data { get; set; }
}

And you configure AutoMapper using this:

Mapper.Initialize(
    cfg =>
    {
        cfg.CreateMap<Source, Destination>()
            .ForMember(
                d => d.Data, 
                c => c.MapFrom(s => JsonConvert.DeserializeObject(s.Data ?? "")
    }
);

When you map a Source object with a value for Data that results in null json (e.g. a null value, an empty string, or the string "null", all of which result in JsonConvert returning null), the value of Destination.Data ends up being set to an empty JObject instead of null.

Is there a way to prevent Automapper from initializing the destination member at all?

There are a few different things you can do but most of them only cover a subset of the cases. For instance, you can add a condition to the mapping to only apply when Source.Data is not null or empty. But this doesn't work if Source.Data is the string "null".

Is there a better way to handle this without needing to add a bunch of special casing conditions on the outside?

Side Note: I can get it working by providing a top level mapping between string and JObject. But that would mean that I have to use the same logic for every case and I ONLY want it to apply to this one property.


Solution

  • AllowNullCollections works per profile, but per property, you can try smth like:

    cfg.CreateMap<Source, Destination>()
       .ForMember(destination => destination.Data, 
                  options => options.AddTransform(data=>data.Count == 0 ? null : data));
    

    The thing is, what you resolve gets mapped again and if AllowNullCollections is false, AM will have to create one for you :) See also this.