读取JSON数据并循环遍历数据以根据条件

时间:2017-04-23 08:19:13

标签: c# arrays json linq

我一直在尝试根据给定的时间获取句点数组中的标题,描述,开始和结束日期,我有以下JSON数据(以下的变量名是 _json < / EM> ):

更新

我想要做的是在json数组中获取标题,描述,开始和结束日期,它的条件将基于json数组中的开始和结束日期。

[
    {
        "ID": "1",
        "Title": "First Title",
        "Description": "First Description",
        "Periods": [
            {
                "StartDate": "2017-04-23 15:30",
                "EndDate": "2017-04-23 15:40"
            },
            {
                "StartDate": "2017-04-23 15:42",
                "EndDate": "2017-04-23 15:45"
            },
            {
                "StartDate": "2017-04-23 15:47",
                "EndDate": "2017-04-23 15:50"
            }
        ]
    },
    {
        "ID" : "2",
        "Title": "Second Title",
        "Description": "Second Description",
        "Periods": [
            {
                "StartDate": "2017-04-23 15:52",
                "EndDate": "2017-04-23 15:55"
            },
            {
                "StartDate": "2017-04-23 15:57",
                "EndDate": "2017-04-23 16:00"
            },
            {
                "StartDate": "2017-04-23 16:02",
                "EndDate": "2017-04-23 16:05"
            }
        ]
    }
]

这是我的代码:

public sealed class Information
{
    public List<Period> Periods;
    public string Title;
    public string Description;
    public int ID;
}

public sealed class Period
{
    public DateTime StartDate;
    public DateTime EndDate;
}

var informations = JsonConvert.DeserializeObject<List<Information>>(_json);

var information = GetData(informations, DateTime.Now);

private Information GetData(List<Information> informations, DateTime dateToCheck)
{
    return informations.Select(x =>
    {
        x.Periods = x.Periods
                     .TakeWhile(y => dateToCheck >= y.StartDate 
                                  && dateToCheck < y.EndDate)
                     .ToList();

        if (x.Periods.Count > 0)
           return x;
        else
            return null;
     }).FirstOrDefault();
 }

但是,它只接受JSON数据的第一个数组(ID:1)和JSON数据中 Periods 的第一个数组,甚至 DateTime.Now 超过 2017-04-23 15:40 ,或 2017 -04-23 15:52 ,它将返回null。

我是否过滤不正确的LINQ或在时间条件之间?

你的回答非常感谢。

第二次更新:

enter image description here

预期输出将如下:

  • 拥有JSON数据,例如:日期时间落入“ID:2”“期间: 2017-04-23 15:57“,那么它只返回 ID no 2 的JSON和下降期间(在这种情况下 2017-04-23 15:57 as StartDate 2017-04-23 16:00作为EndDate ),同时删除其余的期间。所以它就像这个(它基于时间段,日期时间落在哪里,它将确定需要获得哪些数据)

    "ID" : "2",
    "Title": "Second Title",
    "Description": "Second Description",
    "Periods": [ {
       "StartDate": "2017-04-23 15:57",
       "EndDate": "2017-04-23 16:00" }
    

由于

3 个答案:

答案 0 :(得分:2)

根据MSDN,您的查询问题为TakeWhile: -

  

只要指定的条件是,就返回序列中的元素   真正。元素的索引用于谓词的逻辑中   功能

所以在你的查询中它只是检查,直到它找到正确的匹配,然后忽略所有数据。相反,您需要检查整个periods中的状况。

您可以使用FirstOrDefault简化查询,它可以为您提供正确的结果: -

return informations.FirstOrDefault(y => dateToCheck >= y.StartDate 
                                        & dateToCheck < y.EndDate);

如果找不到匹配项,则返回 null ,否则返回第一个Information对象(如果找到匹配项)。

如果您想要返回所有匹配的Periods,请使用Where instaed,您的方法返回类型应更改为IEnumerable<Information>而不是Information

答案 1 :(得分:1)

我认为您需要TakeWhile代替Where

x.Periods = x.Periods
             .Where(y => dateToCheck >= y.StartDate 
                      && dateToCheck < y.EndDate)
             .ToList();

请记住,TakeWhile在条件为false时停止。如果您需要更正式的解释,可以找到here

  

TakeWhile(IEnumerable,Func)   方法通过使用谓词测试源的每个元素并产生   如果结果为true,则为element。枚举在谓词时停止   函数为元素返回false或者source不再包含   元件。

<强>更新

private Information GetFirstMatchingInformationByPeriod(
    List<Information> informations
    , DateTime dateToCheck)
{
    // Find the first information that match your search criteria
    var information = informations.FirstOrDefault(information 
                                                  => information.Periods                                                                         
                                                                .Any(period
                                                    => period.dateToCheck >= period.StartDate 
                                                    && period.dateToCheck < period.EndDate);

    // If not any found, return null.
    if(information == null) return null;

    var firstMatchingPeriod = information.Periods
                                         .First(period => dateToCheck >= period.StartDate 
                                                       && dateToCheck < period.EndDate);

     // Information found. 
     // Change it's periods with a List containin only the first matching period. 
     information.Periods = new List<Period>{ firstMatchingPeriod } ;
     return information;
}

答案 2 :(得分:0)

有一种更易读的方式来编写查询(有效):

private static Information GetData(List<Information> informations, DateTime dateToCheck)
{
    return (from info in informations
            from period in info.Periods
            where dateToCheck >= period.StartDate &&
                  dateToCheck < period.EndDate
            select info).FirstOrDefault();
}