【问题标题】:Accessing multiple arrays in JSON using C#使用 C# 访问 JSON 中的多个数组
【发布时间】:2013-07-11 07:21:38
【问题描述】:

我的 JSON 如下所示:

    {"2013" : [
        { "date":"2013-01-09 12:00:00","height":0 },
        { "date":"2013-01-19 12:00:00","height":3 },
        { "date":"2013-01-29 12:00:00","height":2 }],
    "2012" : [
        { "date":"2012-02-09 12:00:00","height":0 },
        { "date":"2012-02-19 12:00:00","height":4 },
        { "date":"2012-02-29 12:00:00","height":2 }],
    "2011" : [
        { "date":"2011-03-09 12:00:00","height":3 },
        { "date":"2011-03-19 12:00:00","height":8 },
        { "date":"2011-03-29 12:00:00","height":2 }]
   }

我想要做的是获取所有日期和高度,但我只能使用此代码每年完成它:

    public class Report
    {
        public DateTime Date { get; set; }
        public int Height { get; set; }
    }

    JObject data = JObject.Parse(sr);
    var postTitles = from p in data["2013"]
                     select new Report
                     {
                         Date = DateTime.Parse((string)p["date"]),
                         Height = (int)p["height"]
                     };

我正在考虑使用 for 循环,但在 data[" "] 中尝试变量不起作用。我也在考虑做 var postTitles += 声明,但也是不允许的。关于我应该如何去做的任何想法?我正在使用 JSON.NET,建议我每年上一堂课(即 2013 年、2012 年、2011 年),但我希望它们归于一个类,以便更轻松地操作数据。

【问题讨论】:

    标签: c# json windows-phone json.net


    【解决方案1】:

    我对您使用的 LINQ 语法不是很好,但您想要做的是从许多列表中创建一个列表。所以你想使用 LINQ 中的 SelectMany 映射操作。

    var postTitles = data.Children()
            .SelectMany(subitems => subitems.First)
            .Select(dataOfYear =>
                new Report
                    {
                        Date = DateTime.Parse((string)dataOfYear ["date"]),
                        Height = (int)dataOfYear ["height"]
                    }
                );
    

    如果您只想要每年的前 100 份报告,您可以这样做:

    var postTitles = data.Children()
            .SelectMany(subitems => subitems.First)
            .Take(100)
            .Select(dataOfYear =>
                new Report
                    {
                        Date = DateTime.Parse((string)dataOfYear ["date"]),
                        Height = (int)dataOfYear ["height"]
                    }
                );
    

    或者,如果您只是想释放 UI 线程,您可以在后台线程中运行它:

    var postTitles = await Task.Run(() => data.Children()
            .SelectMany(subitems => subitems.First)
            .Select(dataOfYear =>
                new Report
                    {
                        Date = DateTime.Parse((string)dataOfYear ["date"]),
                        Height = (int)dataOfYear ["height"]
                    }
                ));
    

    【讨论】:

    • "dataOfYear =>" 语句后是否缺少某些内容?
    • @CCCC 抱歉,我使用了另一个虚拟结构进行测试,在使用 JSON.Net 加载 json 数据后,我得出了与 PatrikW 相同的结论
    【解决方案2】:

    我转过身,稍微扭曲了马克的回答,想出了这个:

    var postTitles = data.Children() // Select array container properties, like "2013"
            .SelectMany(x => x.First) // Select each subitem from every array
            .Select(r => // Create a report for each item
                new Report
                    {
                        Date = DateTime.Parse((string)r["date"]),
                        Height = (int)r["height"]
                    }
                );
    

    希望内联 cmets 能够充分解释逻辑。

    【讨论】:

    • 它确实有效。谢谢!基于你的问题。数据实际上太大了,所以我的应用程序突然滞后。比如说,如果我要选择前 100 个“报告”,for 循环会起作用吗?因为现在,我正在使用一个 foreach(postTitles 中的 var s)循环,使用 s.Date 和 s.Height 来引用每个循环。如果我将其更改为 for 循环,我将如何处理?
    • @CCCC 查看 Mark 的更新答案以了解该问题的解决方案。
    猜你喜欢
    • 2020-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-07
    • 2011-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多