Buscar un JToken específico por nombre en una jerarquía JObject

Tengo una respuesta Json del servidor, por ejemplo:

{"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 }, 

Y quiero obtener el valor de token ‘text’ de

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

que es una cadena con valor “1.7 km”.

Pregunta: ¿hay alguna función incorporada en NewtonsoftJson lib que se pueda ver así:

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

¿o necesito implementar algún método recursivo que busque JToken por nombre en todos JTokens y JArrays en JObject?

Si está buscando un token muy específico y conoce su camino, puede navegar fácilmente usando el método SelectToken() . Por ejemplo:

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

Si necesita encontrar todas las ocurrencias de un token con un nombre de stack en su JSON, no importa dónde ocurran, entonces sí, necesitaría un método recursivo. Aquí hay uno que podría hacer el truco:

 public static class JsonExtensions { public static List FindTokens(this JToken containerToken, string name) { List matches = new List(); FindTokens(containerToken, name, matches); return matches; } private static void FindTokens(JToken containerToken, string name, List matches) { if (containerToken.Type == JTokenType.Object) { foreach (JProperty child in containerToken.Children()) { 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); } } } } 

Aquí hay una demostración:

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

Aquí está el resultado:

 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 

Esto es bastante simple usando las rutas de JavaScript y el método JToken en JToken . Este método es bastante impresionante y admite tarjetas wilds como las siguientes:

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

Echa un vistazo a este código de muestra:

 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 } } ] }]}"; } } 

Y aquí está la salida:

 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