You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 19:53:14