源对象(JSON),使用JSON。. NET(如果重要的话):
{
"conum" : 1001,
"name" : "CLN Industries Corporation",
"agencyName" : "Murphy, Holmes & Associates, LLC",
"sAA" : [{
"code" : 247,
"description" : "Mechanicu0027s lien - Bond to Discharge - Fixed penalty - where principal has posted Performance and Pa"
}, {
"code" : 277,
"description" : "Mechanicu0027s lien - Bond to Discharge - Open Penalty - where principal has posted Performance and Paym"
}, {
"code" : 505,
"description" : "Indemnity Bonds - Contractoru0027s Indemnity Against Damages where there is a performance bond and addit"
}
]
}
目标对象(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配置和映射:
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"]); });
}
}
除了SaaCodes转换之外,一切都可以工作,其中Automapper将每个条目转换为空saacoode对象(所有属性设置为null)。
我如何/在哪里告诉automapper如何将JSON字段中的项转换为其目标类型?
试一试-
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
{
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"" : ""Mechanicu0027s lien - Bond to Discharge - Fixed penalty - where principal has posted Performance and Pa""
}, {
""code"" : 277,
""description"" : ""Mechanicu0027s lien - Bond to Discharge - Open Penalty - where principal has posted Performance and Paym""
}, {
""code"" : 505,
""description"" : ""Indemnity Bonds - Contractoru0027s Indemnity Against Damages where there is a performance bond and addit""
}
]
}
";
var jsonoObj = JObject.Parse(jsonText);
CorporateRatesInfo dto = mapper.Map<CorporateRatesInfo>(jsonoObj);
}
}
编辑:Per https://docs.automapper.org/en/stable/Configuration.html, Automapper版本6及以上不支持Configure()方法。所以我稍微调整了一下我的答案,以遵循构造函数的方法。
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);
}
}
一个报告,我写了一个简单的解决方案,如果字段名匹配,您可以使用Newtonsoft的反序列化器内的映射器扩展助手方法。我写了一个通用的ResolveJson扩展方法。
public static class MapperExtensions
{
public static T ResolveJson<T>(this JObject jobj, string target)
{
return JsonConvert.DeserializeObject<T>(jobj.SelectToken(target).ToString());
}
}
,然后可以使用下面的
调用CreateMap<JObject, CorporateRatesInfo>()
.ForMember(x => x.SaaCodes,m => { m.MapFrom(s => s.ResolveJson<SaaCode>("sAA"));});
不幸的是,我在更新版本的AutoMapper中遵循了Bookamp的问题,并努力使其工作。
对于其他发现此问题的人,我的替代方法是在以下来源
示例数组
{
'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'
}
}]
}
配置文件示例
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;
}
}