2017-05-19 2 views
0

Json.Net의 Json2Linq를 사용하여 Json 응답을 필터링하려고하는데 필터링 중에 "Newtonsoft.Json.Linq.JProperty에서 하위 값에 액세스 할 수 없습니다."라는 오류가 발생했습니다. 아래의 C#에 내 코드입니다Filter Json이 Facebook에서 응답

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); 
     } 

페이스 북 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": "[email protected]", 
"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

우선, 예비 문제입니다. 당신은 r["id"].Value<string>() == "475729939105078"를 쿼리되지만 JSON의 ID 값은 실제로 :이 동일해야

  "id": "475723939105078" 

. 이 질문에 오타가 있다고 가정합니다.

귀하의 질의는 여러 부분으로 구성되어 있습니다 - 당신은 [*]JSONPath syntax를 사용하여 배열 인덱스 와일드 카드를 나타냅니다 중첩 배열 "friends.data[*].likes.data[*]", 내부의 모든 like 데이터 오브젝트를 통해 반복되는

  1. .

  2. 당신은 당신이 계산에 의해 중복 및 주문을 그룹화하는 것 같다 id == "475723939105078"

  3. 로 해당 개체를 필터링하는 - 나는 .Values<string>() 이후이의 잘 모르겠어요 비록 원시적 특성 반면의 값을 얻을 것입니다 like.data 개체는 사실 프리미티브가 아니므로 쿼리의이 부분은 실패합니다.

또한 LINQ와 Lambda 구문을 혼합하여 작업을 혼란스럽게 만듭니다. 하나를 고르고 그걸 고수 할 것을 권합니다. 다음

쿼리의 첫 두 부분

는 LINQ 구문을 사용하여 달성 될 수

 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; 

또는 사용, λ :

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

마지막 SelectTokens() with JSONPath 사용 :

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

비교를 위해 쿼리에서 "Cannot access child value on Newtonsoft.Json.Linq.JProperty." 오류는 t 사실, 당신이 할 때 rss["friends"]["data"].First().SelectMany(l => l["likes"]) 여분의 첫 번째 배열 항목을 잡아 그래서 like 속성 값 통해 루핑 끝 - 토큰 계층 구조에서 너무 깊은 한 수준입니다.그룹에 관해서는

, 당신의 JSON은 중복 like 데이터의 예를 표시하지 않습니다,하지만 당신은 항상 JTokenEqualityComparer 파악하고 그룹 동일한 JSON 객체로 할 수 있습니다

 var friendLikes = 
      friendLikesFiltered 
      .GroupBy(l => l, new JTokenEqualityComparer()) 
      .OrderBy(g => g.Count()) 
      .Select(g => g.Key); 

(여기에 내가 위해 람다 구문을 사용 사용자 정의 IEqualityComparer<JToken>을 사용하십시오.

샘플 fiddle은 세 가지 버전을 모두 표시합니다.