【问题标题】:C# Lambda Expression for iterating through nested objects用于迭代嵌套对象的 C# Lambda 表达式
【发布时间】:2021-02-25 19:36:05
【问题描述】:

我有以下 JSON,我已将其反序列化为 C# 对象,并希望在每次迭代中提取 INFO_CARD_IDDOCUMENT_NUMREVISION_NM 的值。

{
    "result": {
        "message": "Successfully performed search",
        "columnlist": "INFO_CARD_ID,DOCUMENT_NUM,REVISION_NM,
        "recordcount": 2,
        "rows": [
            {
                "columns": [
                    {
                        "value": "UJ3P25HO3JBPLJZ2HU",
                        "key": "INFO_CARD_ID"
                    },
                    {
                        "value": "DOC1",
                        "key": "DOCUMENT_NUM"
                    },
                    {
                        "value": "05",
                        "key": "REVISION_NM"
                    }
                ]
            },
            {
                "columns": [
                    {
                        "value": "JWQ5TCIV4JC2BCQ4C5",
                        "key": "INFO_CARD_ID"
                    },
                    {
                        "value": "DOC2",
                        "key": "DOCUMENT_NUM"
                    },
                    {
                        "value": "05",
                        "key": "REVISION_NM"
                    }
                ]
            }
        ]
    }
}

这里是 C# 类:

    public class Columns
    {
        public string value { get; set; }
        public string key { get; set; }
    }

    public class Rows
    {
        public IList<Columns> columns { get; set; }
    }

    public class Result
    {
        public string message { get; set; }
        public string columnlist { get; set; }
        public int recordcount { get; set; }
        public IList<Rows> rows { get; set; }
    }

    public class searchOutputModel
    {
        public Result result { get; set; }
    }

到目前为止,我一直在尝试使用以下表达式提取列表中的信息,但没有成功,因为每次迭代都会存储单个值,而不是每次迭代同时存储所有值。

searchResponse = JsonConvert.DeserializeObject<searchOutputModel>(json);

var dynamicList = searchResponse.result.rows.SelectMany(x => x.columns).Where(y => y.key.Contains("INFO_CARD_ID") || y.key.Contains("DOCUMENT_NUM") || y.key.Contains("REVISION_NM")).Select(y => {
        dynamic myValue;
        if (y.key.Contains("INFO_CARD_ID"))
            myValue = new { INFO_CARD_ID = y.value };
        else if (y.key.Contains("DOCUMENT_NUM"))
            myValue = new { DOCUMENT_NUM = y.value };
        else
            myValue = new { REVISION_NM = y.value };
        return myValue;
    }).ToList();

预期输出:

INFO_CARD_ID       DOCUMENT_NUM  REVISION_NM
---------------------------------------------
UJ3P25HO3JBPLJZ2HU DOC1          05
JWQ5TCIV4JC2BCQ4C5 DOC2          05

我知道我在迭代时做错了,因为它会在每次选择时创建新列表,但我不确定如何实现我正在寻找的解决方案。任何帮助表示赞赏。

【问题讨论】:

  • 不要为此使用 LINQ。为您的类提供JsonProperty 属性,以便您可以直接反序列化为所需的类结构。

标签: c# json linq object lambda


【解决方案1】:

我们只需要为每个row 选择一个对象,这里不需要SelectMany。每个属性都可以通过columns.FirstOrDefault获取。

我建议您为此创建一个适当的类,而不是使用dynamic,但这与下面的逻辑几乎没有区别。

不知道你为什么在column.key 支票上使用Contains,我用过==

var dynamicList = searchResponse.result.rows.Select(r => 
    new {
        INFO_CARD_ID = r.columns.FirstOrDefault(c => c.key == "INFO_CARD_ID")?.value,
        DOCUMENT_NUM = r.columns.FirstOrDefault(c => c.key == "DOCUMENT_NUM")?.value,
        REVISION_NM = r.columns.FirstOrDefault(c => c.key == "REVISION_NM")?.value,
    }).ToList();

【讨论】:

  • 谢谢@Charlieface,这个肯定回答了我的问题。干杯!
【解决方案2】:

如果将每个Rows 对象转换为Dictionary,则可以使用Dictionary 创建对象:

var ans = searchResponse.result.rows
            .Select(r => r.columns.ToDictionary(c => c.key, c => c.value))
            .Select(cd => new {
                INFO_CARD_ID = cd["INFO_CARD_ID"],
                DOCUMENT_NUM = cd["DOCUMENT_NUM"],
                REVISION_NM = cd["REVISION_NM"]
            });

【讨论】:

  • 也感谢@NetMage 的解决方案 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-20
  • 1970-01-01
相关资源
最近更新 更多