如何用AutoMapper映射实体类与DTO?GetAll接口映射异常排查
问题分析与解决方案
你的GetAll接口映射失败主要有三个核心问题,咱们一步步拆解解决:
1. 类型不匹配:DTO的MetaData类型与元数据类名不一致
看代码就能发现,SrcDTO里的MetaData属性类型是SourceMetaData,但实际定义的元数据类叫SRCMetaData——这俩类型完全不搭,AutoMapper根本找不到对应的转换关系!
解决方法:统一类型名称,二选一即可:
- 把元数据类改名为
SourceMetaData:
public class SourceMetaData { [JsonProperty("Input")] public SourceInput SourceInput { get; set; } // 注意这里还要改访问修饰符,后面会说 [JsonProperty("OutPut")] public SourceOutput SourceOutput { get; set; } [JsonProperty("Position")] public SourcePosition SourcePosition { get; set; } }
- 或者把
SrcDTO里的MetaData类型改成SRCMetaData:
public class SrcDTO { // ... 其他属性保持不变 [JsonProperty("MetaData")] public SRCMetaData MetaData { get; set; } }
2. 元数据类属性是私有访问修饰符,无法被Json.NET反序列化
你的SRCMetaData(或改名后的SourceMetaData)里的SourceInput、SourceOutput、SourcePosition都是private属性,Json.NET默认只能处理public成员,反序列化时这些属性会直接被忽略,导致MetaData对象为空或不完整。
解决方法:把这些属性改成public:
public class SourceMetaData { [JsonProperty("Input")] public SourceInput SourceInput { get; set; } [JsonProperty("OutPut")] public SourceOutput SourceOutput { get; set; } [JsonProperty("Position")] public SourcePosition SourcePosition { get; set; } }
3. AutoMapper映射时未指定反序列化的目标类型
当前Src到SrcDTO的映射配置里,JsonConvert.DeserializeObject(jo.MetaData)没有指定具体类型,默认会返回JObject,但SrcDTO的MetaData是强类型对象,AutoMapper没法自动把JObject转换成你的元数据类,自然映射失败。
解决方法:修改AutoMapper配置,指定反序列化的目标类型,同时加空值判断避免报错:
CreateMap<Src, SrcDTO>() .ForMember(x => x.MetaData, cfg => cfg.MapFrom(jo => string.IsNullOrEmpty(jo.MetaData) ? null : JsonConvert.DeserializeObject<SourceMetaData>(jo.MetaData) // 这里的类型要和你修正后的一致 ) );
验证修复后的完整流程
- 确保元数据类的属性都是
public,且与DTO中的类型完全匹配 - 更新AutoMapper的映射规则,明确指定反序列化的具体类型
- 测试GetAll接口,此时
Src实体中的MetaData字符串会被正确反序列化为对应的强类型对象,映射成功
另外,建议你写个单元测试验证映射逻辑,比如:
[Test] public void TestSrcToSrcDtoMapping() { var srcEntity = new SRC { Id = 1, Name = "Test", MetaData = "{\"Input\":{\"Name\":\"TestInput\",\"Key\":\"testkey\",\"AgentId\":1,\"Type\":2},\"OutPut\":{\"Name\":\"TestOutput\",\"Key\":\"outputkey\",\"AgentId\":1,\"Type\":1},\"Position\":{\"Lat\":\"42°21'30\\\"N\",\"Long\":\"71°03'37\\\"W\"}}" }; var mapper = new MapperConfiguration(cfg => { cfg.CreateMap<Src, SrcDTO>() .ForMember(x => x.MetaData, cfg => cfg.MapFrom(jo => JsonConvert.DeserializeObject<SourceMetaData>(jo.MetaData))); }).CreateMapper(); var dto = mapper.Map<SrcDTO>(srcEntity); Assert.NotNull(dto.MetaData); Assert.AreEqual("TestInput", dto.MetaData.SourceInput.Name); }
内容的提问来源于stack exchange,提问作者Abhishek B.
相关产品推荐
相关产品推荐

