在JObject层次结构中按名称搜索特定的JToken

我有一些来自服务器的Json响应,例如:

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

我想从中获取令牌’text’的值

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

这是一个值为“1.7 km”的字符串。

问题: NewtonsoftJson lib中是否有任何内置函数,如下所示:

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

或者我是否需要实现一些递归方法,它将在JObject中的所有JTokens和JArrays中按名称搜索JToken?

如果您正在寻找一个非常特定的令牌并知道它的路径,您可以使用内置的SelectToken()方法轻松导航到它。 例如:

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

如果你需要在JSON中找到具有给定名称的令牌的所有出现,无论它们出现在何处,那么是的,你需要一个递归方法。 这是一个可能做到这一点的技巧:

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

这是一个演示:

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

这是输出:

 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 

使用SelectTokens上的javascript路径和SelectTokens方法非常简单。 这种方法非常棒,支持如下的通配符:

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

看看这个示例代码:

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

这是输出:

 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