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.
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.