如何使用AutoMapper将复杂对象映射为扁平对象列表?
使用AutoMapper将复杂对象转换为扁平对象列表
我需要用AutoMapper把复杂的Source对象转换成扁平的对象列表,同时保留Symbol信息。尝试了官方文档里的ITypeConverter接口,但映射没成功。相关C#类定义、示例数据和期望的转换结果如下:
相关C#类定义
public class Source { public Request Request { get; set; } public Error Error { get; set; } public Records Records { get; set; } public string Service { get; set; } } public class Records { public List<Record> Record { get; set; } } public class Fields { public List<Field> Field { get; set; } } public class Field { public string Id { get; set; } public string Name { get; set; } public string Value { get; set; } } public class Request { public string RequestedSymbols { get; set; } public string RequestedFields { get; set; } public string Host { get; set; } public string Id { get; set; } } public class Error { public string Code { get; set; } public string Description { get; set; } } public class Record { public Fields Fields { get; set; } public string Req_sym { get; set; } public string Key { get; set; } public string Stale { get; set; } }
示例复杂对象数据
{ "Request": { "RequestedSymbols": "ABC,BCD,CDE", "RequestedFields": "ASK,BID,LAST", "Host": "XYZ", "Id": "123" }, "Error": { "Code": "0", "Description": "" }, "Records": { "Record": [ { "Fields": { "Field": [ { "Id": "200", "Name": "ASK", "Value": "43.75" }, { "Id": "100", "Name": "BID", "Value": "43.73" }, { "Id": "300", "Name": "LAST", "Value": "43.73" } ] }, "Req_sym": "ABC", "Key": "ABC", "Stale": "" }, { "Fields": { "Field": [ { "Id": "200", "Name": "ASK", "Value": "76.18" }, { "Id": "100", "Name": "BID", "Value": "76.17" }, { "Id": "300", "Name": "LAST", "Value": "76.19" } ] }, "Req_sym": "BCD", "Key": "BCD", "Stale": "" }, { "Fields": { "Field": [ { "Id": "200", "Name": "ASK", "Value": "16.34" }, { "Id": "100", "Name": "BID", "Value": "16.33" }, { "Id": "300", "Name": "LAST", "Value": "16.33" } ] }, "Req_sym": "CDE", "Key": "CDE", "Stale": "" } ] }, "Service": "XYZ" }
期望转换后的扁平对象列表
[ { "Symbol": "ABC", "ASK": 43.75, "BID": 43.73, "LAST": 43.73 }, { "Symbol": "BCD", "ASK": 76.18, "BID": 76.17, "LAST": 76.19 }, { "Symbol": "CDE", "ASK": 16.34, "BID": 16.33, "LAST": 16.33 } ]
解决方案
1. 定义目标DTO类
先创建匹配期望结构的DTO:
public class SymbolPriceDto { public string Symbol { get; set; } public decimal ASK { get; set; } public decimal BID { get; set; } public decimal LAST { get; set; } }
2. 实现自定义类型转换器
因为要从Source转换为List<SymbolPriceDto>,需要实现ITypeConverter<Source, List<SymbolPriceDto>>,在转换器里处理嵌套结构的解析逻辑:
public class SourceToSymbolPriceListConverter : ITypeConverter<Source, List<SymbolPriceDto>> { public List<SymbolPriceDto> Convert(Source source, List<SymbolPriceDto> destination, ResolutionContext context) { var result = new List<SymbolPriceDto>(); if (source?.Records?.Record == null) return result; foreach (var record in source.Records.Record) { var dto = new SymbolPriceDto { Symbol = record.Req_sym }; foreach (var field in record.Fields.Field) { if (decimal.TryParse(field.Value, out var value)) { switch (field.Name) { case "ASK": dto.ASK = value; break; case "BID": dto.BID = value; break; case "LAST": dto.LAST = value; break; } } } result.Add(dto); } return result; } }
3. 配置AutoMapper映射
在AutoMapper配置中注册这个自定义转换器:
var configuration = new MapperConfiguration(cfg => { cfg.CreateMap<Source, List<SymbolPriceDto>>() .ConvertUsing<SourceToSymbolPriceListConverter>(); }); // 可选:验证配置合法性,排查映射问题 configuration.AssertConfigurationIsValid(); var mapper = configuration.CreateMapper();
4. 执行映射
现在可以直接完成转换:
Source sourceData = // 你的Source对象实例 List<SymbolPriceDto> flatList = mapper.Map<List<SymbolPriceDto>>(sourceData);
关键注意点
- 转换器中加入了空值判断,避免空引用异常
- 使用
decimal.TryParse确保字段值转换的类型安全 - 后续新增字段时,只需在DTO类和转换器的switch分支中添加对应处理逻辑即可
内容的提问来源于stack exchange,提问作者Narendra Jangir
相关产品推荐
相关产品推荐

