过滤来自Facebook的Json回复

时间:2017-05-19 17:02:50

标签: c# json linq lambda json.net

我正在尝试使用Json.Net的Json2Linq过滤Json响应,但在过滤期间发生错误“无法访问Newtonsoft.Json.Linq.JProperty上的子值”。 下面是我在C#上的代码

   JObject rss = JObject.Parse(userJson);

        try
        {
            var FriendsLikes = from c in rss["friends"].First()["data"]
                               .SelectMany(l => l["likes"]
                               .Select(d => d["data"]).Where(r => r["id"].Value<string>() == "475729939105078")).Values<string>()
                               group c by c into g
                               orderby g.Count() descending
                               select new { FriendsLikes = g.Key };

            foreach (var item in FriendsLikes)
            {
                System.Diagnostics.Debug.WriteLine(item.FriendsLikes);
            }
        }
        catch (System.Exception e)
        {
            System.Diagnostics.Debug.WriteLine(e.Message);
        }

Facebook Json回复

{
"id": "999999999084775",
"name": "Alex Xx",
"first_name": "Alex",
"last_name": "Xx",
"gender": "male",
"link": "https://www.facebook.com/app_scoped_user_id/101999999999999/",
"locale": "en_US",
"email": "alexxxx@gmail.com",
"picture": {
    "data": {
        "url": "https://scontent.xx.fbcdn.net/v/t1.0-1/p50x50/18341660_101370733774524_7009999999999957463_n.jpg?oh=ec8675dfe23bbda00b6048647af62875&oe=59C0F7DF",
        "is_silhouette": false
    }
},
"friends": {
    "data": [{
        "id": "10213045626997937",
        "name": "Jayson Raga",
        "first_name": "Jayson",
        "last_name": "Ragasa",
        "gender": "male",
        "link": "https://www.facebook.com/app_scoped_user_id/10213045626997937/",
        "locale": "en_US",
        "picture": {
            "data": {
                "url": "https://scontent.xx.fbcdn.net/v/t1.0-1/p50x50/16114608_10211941851924250_4611916174586601978_n.jpg?oh=de4c0a7839e7e9e7ef6e29e18b885ef898&oe=59A99999",
                "is_silhouette": false
            }
        },
        "likes": {
            "data": [{
                "live_videos": {
                    "data": [{
                        "from": {
                            "name": "MyBeat",
                            "id": "475728822105078"
                        },
                        "permalink_url": "/MyBeat/videos/1283448691726531/",
                        "description": "@[141752355816253]:behind the decks live",
                        "creation_time": "2016-07-03T17:20:49+0000",
                        "id": "1261428671666530"
                    }]
                },
                "id": "475723939105078"
            }]
        }
    }]
},

}

我的代码中的目标是过滤所有喜欢的朋友并返回ID中的所有喜欢:475723939105078

1 个答案:

答案 0 :(得分:1)

首先,一个初步的问题。您正在查询like,但JSON中的ID值实际上是:

"friends.data[*].likes.data[*]"

这些必须相同。我认为这是问题中的拼写错误。

您的查询包含几个部分 -

  1. 您正在遍历嵌套数组[*]内的所有id == "475723939105078"数据对象,其中like.data表示使用JSONPath syntax的数组索引通配符。

    < / LI>
  2. 您正在使用 var id = "475723939105078"; var friendLikesFiltered = from f in rss["friends"]["data"] // Loop through all entries f in friends.data from l in f["likes"]["data"] // Then loop all entries in likes.data where (string)l["id"] == id // where like.id == friendId select l;

  3. 过滤这些对象
  4. 您似乎正在按重要次数对重复项进行分组 - 虽然我不确定这一点,因为.Values<string>()旨在获取原始属性的值,而 var id = "475723939105078"; var friendLikesFiltered = rss["friends"]["data"] .SelectMany(f => f["likes"]["data"]) .Where(l => (string)l["id"] == id); 实际上,对象不是原语,因此查询的这一部分失败。

  5. 此外,您正在混合使用LINQ和Lambda语法,这会让事情变得更加混乱。我建议选择一个并坚持下去。

    查询的前两部分可以使用LINQ语法完成,如下所示:

            var id = "475723939105078";
            var friendLikesFiltered
                = rss.SelectTokens("friends.data[*].likes.data[*]")
                .Where(l => (string)l["id"] == id);
    

    或者使用lambda:

    "Cannot access child value on Newtonsoft.Json.Linq.JProperty."

    最后使用SelectTokens() with JSONPath

    rss["friends"]["data"].First().SelectMany(l => l["likes"])

    为了进行比较,在您的查询中,First()错误是由以下事实引起的:当您执行SelectMany()时,额外like抓取第一个数组条目,以便{{1}最终循环遍历 like属性值 - 这是令牌层次结构中的一个级别。

    至于分组,您的JSON没有显示重复 var friendLikes = friendLikesFiltered .GroupBy(l => l, new JTokenEqualityComparer()) .OrderBy(g => g.Count()) .Select(g => g.Key); 数据的示例,但您始终可以JTokenEqualityComparer来识别和分组相同的JSON对象:

    {{1}}

    (这里我使用lambda语法来使用自定义IEqualityComparer<JToken>。)

    示例fiddle显示所有三个版本。