相关文章推荐
不爱学习的甘蔗  ·  首届CCF ...·  1 年前    · 
乐观的番茄  ·  Difference BETWEEN ...·  1 年前    · 
慷慨大方的柚子  ·  c++ - How to create ...·  1 年前    · 
潇洒的充电器  ·  Django Channels ...·  1 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams "conum" : 1001, "name" : "CLN Industries Corporation", "agencyName" : "Murphy, Holmes & Associates, LLC", "sAA" : [{ "code" : 247, "description" : "Mechanic\u0027s lien - Bond to Discharge - Fixed penalty - where principal has posted Performance and Pa" "code" : 277, "description" : "Mechanic\u0027s lien - Bond to Discharge - Open Penalty - where principal has posted Performance and Paym" "code" : 505, "description" : "Indemnity Bonds - Contractor\u0027s Indemnity Against Damages where there is a performance bond and addit"

Destination Object (C#):

public class CorporateRatesInfo
    public string Conum { get; set; }
    public string Name { get; set; }
    public string AgencyName { get; set; }
    public List<SaaCode> SaaCodes { get; set; }
public class SaaCode
    public string Code { get; set; }
    public string Description { get; set; }

Automapper config and mappings:

var config = new MapperConfiguration(cfg =>
    cfg.CreateMap<JObject, CorporateRatesInfo>();
    cfg.AddProfile<CorporateRatesProfile>();
//config.AssertConfigurationIsValid();
_mapper = config.CreateMapper();
public class CorporateRatesProfile : Profile
    protected override void Configure()
        CreateMap<JObject, CorporateRatesInfo>()
            .ForMember("SaaCodes", cfg => { cfg.MapFrom(jo => jo["sAA"]); })
            .ForMember("Conum", cfg => { cfg.MapFrom(jo => jo["conum"]); })
            .ForMember("Name", cfg => { cfg.MapFrom(jo => jo["name"]); })
            .ForMember("AgencyName", cfg => { cfg.MapFrom(jo => jo["agencyName"]); });

Everything works except for the SaaCodes conversion, where Automapper converts each entry into an empty SaaCode object (all properties set to null).

How/where do I tell automapper how to convert items in that JSON field into its destination type?

public string Conum { get; set; } public string Name { get; set; } public string AgencyName { get; set; } public List<SaaCode> SaaCodes { get; set; } public class SaaCode public string Code { get; set; } public string Description { get; set; } public class CorporateRatesProfile : Profile protected override void Configure() CreateMap<JObject, SaaCode>() .ForMember("Code", cfg => { cfg.MapFrom(jo => jo["code"]); }) .ForMember("Description", cfg => { cfg.MapFrom(jo => jo["description"]); }); CreateMap<JObject, CorporateRatesInfo>() .ForMember("SaaCodes", cfg => { cfg.MapFrom(jo => jo["sAA"]); }) .ForMember("Conum", cfg => { cfg.MapFrom(jo => jo["conum"]); }) .ForMember("Name", cfg => { cfg.MapFrom(jo => jo["name"]); }) .ForMember("AgencyName", cfg => { cfg.MapFrom(jo => jo["agencyName"]); }); class Program static void Main(string[] args) var config = new MapperConfiguration(cfg => cfg.CreateMap<JObject, CorporateRatesInfo>(); cfg.AddProfile<CorporateRatesProfile>(); //config.AssertConfigurationIsValid(); var mapper = config.CreateMapper(); var jsonText = @" ""conum"" : 1001, ""name"" : ""CLN Industries Corporation"", ""agencyName"" : ""Murphy, Holmes & Associates, LLC"", ""sAA"" : [{ ""code"" : 247, ""description"" : ""Mechanic\u0027s lien - Bond to Discharge - Fixed penalty - where principal has posted Performance and Pa"" ""code"" : 277, ""description"" : ""Mechanic\u0027s lien - Bond to Discharge - Open Penalty - where principal has posted Performance and Paym"" ""code"" : 505, ""description"" : ""Indemnity Bonds - Contractor\u0027s Indemnity Against Damages where there is a performance bond and addit"" var jsonoObj = JObject.Parse(jsonText); CorporateRatesInfo dto = mapper.Map<CorporateRatesInfo>(jsonoObj);

EDIT: Per https://docs.automapper.org/en/stable/Configuration.html, Automapper version 6 and above does not support Configure() method. So I've adjusted my answer slightly to follow the constructor approach.

public class CorporateRatesInfo
    public string Conum { get; set; }
    public string Name { get; set; }
    public string AgencyName { get; set; }
    public List<SaaCode> SaaCodes { get; set; }
public class SaaCode
    public string Code { get; set; }
    public string Description { get; set; }
public class CorporateRatesProfile : Profile
    public CorporateRatesProfile()
        CreateMap<JToken, SaaCode>()
            .ForMember("Code", cfg => { cfg.MapFrom(jo => jo["code"]); })
            .ForMember("Description", cfg => { cfg.MapFrom(jo => jo["description"]); });
        CreateMap<JToken, CorporateRatesInfo>()
            .ForMember("SaaCodes", cfg => { cfg.MapFrom(jo => jo["sAA"]); })
            .ForMember("Conum", cfg => { cfg.MapFrom(jo => jo["conum"]); })
            .ForMember("Name", cfg => { cfg.MapFrom(jo => jo["name"]); })
            .ForMember("AgencyName", cfg => { cfg.MapFrom(jo => jo["agencyName"]); });
class Program
    static void Main(string[] args)
        var config = new MapperConfiguration(cfg =>
            cfg.AddProfile<CorporateRatesProfile>();
        var mapper = config.CreateMapper();
        var jsonText =  @"{""conum"":1001,""name"":""CLN Industries Corporation"",""agencyName"":""Murphy, Holmes & Associates, LLC"",""sAA"":[{""code"":247,""description"":""Mechanic's lien - Bond to Discharge - Fixed penalty - where principal has posted Performance and Pa""},{""code"":277,""description"":""Mechanic's lien - Bond to Discharge - Open Penalty - where principal has posted Performance and Paym""},{""code"":505,""description"":""Indemnity Bonds - Contractor's Indemnity Against Damages where there is a performance bond and addit""}]}";
        var jsonoObj = JObject.Parse(jsonText);
        CorporateRatesInfo dto = mapper.Map<CorporateRatesInfo>(jsonoObj);
                Fantastic!  I tried similar, but I was thinking the source type was going to be a string.  :(
– SvdSinner
                Jun 30, 2016 at 18:05
                The CorporateRatesProfile implementation only works up to version 4.x. After 5.0, it's obsolete, and you must use this approach instead (and cleaner IMHO) automapper.readthedocs.io/en/latest/…
– CokoBWare
                Apr 3, 2018 at 15:12

A report, I wrote simple solution if the field names match you can use Newtonsoft's deserializer inside the mapper extension helper method. I wrote a generic ResolveJson extension method.

public static class MapperExtensions
    public static T ResolveJson<T>(this JObject jobj, string target)
        return JsonConvert.DeserializeObject<T>(jobj.SelectToken(target).ToString());

which you can then call by using the below

CreateMap<JObject, CorporateRatesInfo>()
    .ForMember(x => x.SaaCodes,m => { m.MapFrom(s => s.ResolveJson<SaaCode>("sAA"));});

Unfortunately, I followed Bookamp's question in newer versions of AutoMapper and struggled to get this working.

My alternative approach for anyone else finding this issue was found on the following source

Example Array

'Items': [{ 'Id': '1', 'EmployeeNo': '1001', 'FirstName': 'Rajat', 'LastName': 'Kumar', 'Gender': { 'Id': '1', 'ShortName': 'M', 'FullName': 'Male' 'Id': '2', 'EmployeeNo': '1003', 'FirstName': 'Lisa', 'LastName': 'David', 'Gender': { 'Id': '2', 'ShortName': 'F', 'FullName': 'Female'

Example Profile Configuration

            CreateMap<JObject, List<User>>().ConvertUsing<JObjectToUserListConverter>();
        var employeeMap = CreateMap<JToken, User>();
        employeeMap.ForMember(x => x.Id, y => y.MapFrom(j => j.SelectToken(".Id")));
        employeeMap.ForMember(x => x.DisplayName, y => y.MapFrom(j => j.SelectToken(".LastName").ToString() + ", " + j.SelectToken(".FirstName").ToString()));
        employeeMap.ForMember(x => x.Gender, y => y.MapFrom(j => j.SelectToken(".Gender.FullName")));
        employeeMap.ForMember(x => x.Login, y => y.MapFrom(j => j.SelectToken(".Login")));

TypeConverter

public class JObjectToUserListConverter : ITypeConverter<JObject, List<User>>
    public List<User> Convert(JObject source, List<User> destination, ResolutionContext context)
        var userList = new List<User>();
        var tokenCountItems = source.SelectTokens("Items").Children().Count();
        for (int i = 0; i < tokenCountItems; i++)
                var token = source.SelectToken($"Items[{i}]");
                var result = new User();
                if (token != null)
                    result = context.Mapper.Map<JToken, User>(token);
                userList.Add(result);
        return userList;
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.