如何使用AutoMapper映射包含JArray属性的目标模型?
问题描述
源JObject
var source = new JObject { { "XCV", Guid.NewGuid().ToString() }, { "store", "abc" }, { "productAId", "123" }, { "productAName", "xxxxxx" }, { "productBId", "456" }, { "productBName", "yyyyyy" }, };
自定义模型
public class StoreProductModel { public string TransactionId { get; set; } public JArray Data { get; set; } }
期望转换后的JSON结构
{ "transactionId": "...", "data": [ { "store": "abc", "productA": { "id": "123", "name": "xxxxxx" }, "productB": { "id": "456", "name": "yyyyyy" } } ] }
尝试的AutoMapper配置
#region JValue - object CreateMap<JValue, object>().ConvertUsing(source => source.Value); #endregion #region JObject - StoreProductModel CreateMap<JObject, StoreProductModel>() .ForMember(dest => dest.TransactionId, opt => { opt.MapFrom(src => src["XCV"]); }) .ForPath(dest => dest.Data[0]["productA"]["id"], opt => { opt.MapFrom(src => src["productAId"]); }) .ForPath(dest => dest.Data[0]["productA"]["name"], opt => { opt.MapFrom(src => src["productAName"]); }); #endregion
抛出的异常
"Only member accesses are allowed. dest => dest.Data.get_Item(0).get_Item("productA").get_Item("id") (Parameter 'destinationMember')"} System.ArgumentOutOfRangeException
已知可以直接初始化StoreProductModel赋值,但希望了解能否通过AutoMapper实现从JObject到含嵌套JArray属性的自定义模型的映射,使用的AutoMapper版本为12.0.1。
解决方案
AutoMapper的ForPath仅支持类的属性、字段这类成员访问,不支持索引器调用(如Data[0]、["productA"]),所以原配置会触发异常。可以通过以下两种方式实现映射:
方式一:自定义值转换器
创建专门的转换器来构建StoreProductModel的Data属性:
public class JObjectToStoreProductDataConverter : IValueConverter<JObject, JArray> { public JArray Convert(JObject source, ResolutionContext context) { var item = new JObject { ["store"] = source["store"], ["productA"] = new JObject { ["id"] = source["productAId"], ["name"] = source["productAName"] }, ["productB"] = new JObject { ["id"] = source["productBId"], ["name"] = source["productBName"] } }; return new JArray(item); } }
修改AutoMapper配置:
CreateMap<JObject, StoreProductModel>() .ForMember(dest => dest.TransactionId, opt => opt.MapFrom(src => src["XCV"])) .ForMember(dest => dest.Data, opt => opt.ConvertUsing<JObjectToStoreProductDataConverter>());
方式二:直接在MapFrom中构建结构
无需额外创建转换器,直接在MapFrom中完成JArray的构建逻辑:
CreateMap<JObject, StoreProductModel>() .ForMember(dest => dest.TransactionId, opt => opt.MapFrom(src => src["XCV"])) .ForMember(dest => dest.Data, opt => opt.MapFrom(src => new JArray(new JObject { ["store"] = src["store"], ["productA"] = new JObject { ["id"] = src["productAId"], ["name"] = src["productAName"] }, ["productB"] = new JObject { ["id"] = src["productBId"], ["name"] = src["productBName"] } }) ));
两种方式都能绕过AutoMapper对ForPath的限制,直接生成符合要求的嵌套JArray结构,完成源JObject到StoreProductModel的映射。
内容的提问来源于stack exchange,提问作者Vanderwood
相关产品推荐
相关产品推荐

