wake-up-neo.com

Suchen nach einem bestimmten JToken nach Namen in einer JObject-Hierarchie

Ich habe eine Json-Antwort vom Server, zum Beispiel:

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

Und ich möchte den Wert von Token 'Text' abrufen 

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

dies ist eine Zeichenfolge mit dem Wert "1,7 km".

Frage: Gibt es in NewtonsoftJson lib eine eingebaute Funktion, die wie folgt aussehen kann:

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

oder muss ich eine rekursive Methode implementieren, die JToken in allen JTokens und JArrays in JObject nach Namen durchsucht?

25
Dima Serdechnyi

Wenn Sie nach einem ganz bestimmten Token suchen und den Pfad zu diesem kennen, können Sie einfach mit der integrierten SelectToken()-Methode dorthin navigieren. Zum Beispiel:

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

Wenn Sie alle Vorkommen eines Tokens mit einem bestimmten Namen in Ihrem JSON suchen müssen, unabhängig davon, wo sie auftreten, müssen Sie eine rekursive Methode verwenden. Hier ist einer, der den Trick tun könnte:

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

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

Hier ist die Ausgabe:

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
63
Brian Rogers

Dies ist ziemlich einfach, wenn Sie die json-Pfade und die SelectTokens -Methode für JToken verwenden. Diese Methode ist ziemlich beeindruckend und unterstützt Platzhalter wie die folgenden:

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

Schauen Sie sich diesen Beispielcode an:

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

Und hier ist die Ausgabe:

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
14
mhand

Wenn Sie alle Werte einer Eigenschaft unabhängig davon, wo sie auftritt, erhalten möchten, können Sie die von @ brian-rogers beschriebene Rekursion verwenden. Verwenden Sie SelectToken wie von @mhand vorgeschlagen:

Um alle Werte von duration.text abzurufen, können Sie SelectToken und Linq verwenden:

var list = jObject.SelectTokens("$..duration.text")
           .Select(t => t.Value<string>())
           .ToList();

Weitere Informationen: JSON mit SelectToken abfragen

0
andersh