2013-10-28 14 views
21

Mam odpowiedź JSON z serwera, na przykład:Szukasz konkretnej JToken nazwy w hierarchii JObject

{"routes" : [ 
    { 
    "bounds" : { 
     "northeast" : { 
      "lat" : 50.4639653, 
      "lng" : 30.6325177 
     }, 
     "southwest" : { 
      "lat" : 50.4599625, 
      "lng" : 30.6272425 
     } 
    }, 
    "copyrights" : "Map data ©2013 Google", 
    "legs" : [ 
     { 
      "distance" : { 
       "text" : "1.7 km", 
       "value" : 1729 
      }, 
      "duration" : { 
       "text" : "4 mins", 
       "value" : 223 
      }, 

I chcę, aby uzyskać wartość symboliczną „tekst” z

 "legs" : [ 
     { 
      "distance" : { 
       "text" : "1.7 km", 
       "value" : 1729 
      }, 

który jest łańcuchem o wartości "1,7 km".

Pytanie: jest jakaś funkcja wbudowany w NewtonsoftJson lib, które mogą być wyglądać następująco:

public string(or JToken) GetJtokenByName(JObject document, string jtokenName) 

czy muszę wdrożyć pewne rekurencyjną metodę, która będzie wyszukiwania JToken wg nazwy we wszystkich JTokens i JArrays w JObject?

Odpowiedz

44

Jeśli szukasz bardzo konkretnego tokena i znasz ścieżkę do niego, możesz z łatwością przejść do niego, korzystając z wbudowanej metody SelectToken(). Na przykład:

string distance = jObject.SelectToken("routes[0].legs[0].distance.text").ToString(); 

Jeśli trzeba znaleźć wszystkie wystąpienia tokena o danej nazwie w Twojej JSON, bez względu na to, gdzie one występują, to tak, że ty potrzebujesz metody rekurencyjnej. Tutaj jest jeden, który może załatwić sprawę:

public static class JsonExtensions 
{ 
    public static List<JToken> FindTokens(this JToken containerToken, string name) 
    { 
     List<JToken> matches = new List<JToken>(); 
     FindTokens(containerToken, name, matches); 
     return matches; 
    } 

    private static void FindTokens(JToken containerToken, string name, List<JToken> matches) 
    { 
     if (containerToken.Type == JTokenType.Object) 
     { 
      foreach (JProperty child in containerToken.Children<JProperty>()) 
      { 
       if (child.Name == name) 
       { 
        matches.Add(child.Value); 
       } 
       FindTokens(child.Value, name, matches); 
      } 
     } 
     else if (containerToken.Type == JTokenType.Array) 
     { 
      foreach (JToken child in containerToken.Children()) 
      { 
       FindTokens(child, name, matches); 
      } 
     } 
    } 
} 

tu jest demo:

class Program 
{ 
    static void Main(string[] args) 
    { 
     string json = @" 
     { 
      ""routes"": [ 
       { 
        ""bounds"": { 
         ""northeast"": { 
          ""lat"": 50.4639653, 
          ""lng"": 30.6325177 
         }, 
         ""southwest"": { 
          ""lat"": 50.4599625, 
          ""lng"": 30.6272425 
         } 
        }, 
        ""legs"": [ 
         { 
          ""distance"": { 
           ""text"": ""1.7 km"", 
           ""value"": 1729 
          }, 
          ""duration"": { 
           ""text"": ""4 mins"", 
           ""value"": 223 
          } 
         }, 
         { 
          ""distance"": { 
           ""text"": ""2.3 km"", 
           ""value"": 2301 
          }, 
          ""duration"": { 
           ""text"": ""5 mins"", 
           ""value"": 305 
          } 
         } 
        ] 
       } 
      ] 
     }"; 

     JObject jo = JObject.Parse(json); 

     foreach (JToken token in jo.FindTokens("text")) 
     { 
      Console.WriteLine(token.Path + ": " + token.ToString()); 
     } 
    } 
} 

Oto wynik:

routes[0].legs[0].distance.text: 1.7 km 
routes[0].legs[0].duration.text: 4 mins 
routes[0].legs[1].distance.text: 2.3 km 
routes[0].legs[1].duration.text: 5 mins 
+0

Dzięki @Brian Rogers, to było bardzo pomocne. – mack

+0

Dzięki, uratowałeś mój dzień! –

11

Jest to bardzo proste przy użyciu javascript ścieżki i tym SelectTokens metoda na JToken. Metoda ta jest dość niesamowite i obsługuje karty Wilds, takich jak:

jObject.SelectTokens("routes[*].legs[*].*.text")

sprawdź ten przykładowy kod:

private class Program 
{ 
    public static void Main(string[] args) 
    { 
     string json = GetJson(); 
     JObject jObject = JObject.Parse(json); 

     foreach (JToken token in jObject.SelectTokens("routes[*].legs[*].*.text")) 
     { 
      Console.WriteLine(token.Path + ": " + token); 
     } 
    } 

    private static string GetJson() 
    { 
     return @" { 
     ""routes"": [ 
     { 
      ""bounds"": { 
       ""northeast"": { 
        ""lat"": 50.4639653, 
        ""lng"": 30.6325177 
       }, 
       ""southwest"": { 
        ""lat"": 50.4599625, 
        ""lng"": 30.6272425 
       } 
      }, 
      ""legs"": [ 
       { 
        ""distance"": { 
         ""text"": ""1.7 km"", 
         ""value"": 1729 
        }, 
        ""duration"": { 
         ""text"": ""4 mins"", 
         ""value"": 223 
        } 
       }, 
       { 
        ""distance"": { 
         ""text"": ""2.3 km"", 
         ""value"": 2301 
        }, 
        ""duration"": { 
         ""text"": ""5 mins"", 
         ""value"": 305 
        } 
       } 
      ] 
     }]}"; 
    } 
} 

A oto wyjście:

routes[0].legs[0].distance.text: 1.7 km 
routes[0].legs[0].duration.text: 4 mins 
routes[0].legs[1].distance.text: 2.3 km 
routes[0].legs[1].duration.text: 5 mins 
+2

Nie wiedziałem o * symbolu wieloznacznym! Próbuję tego teraz. To może zaoszczędzić tyle czasu ... –

Powiązane problemy