programing

JObject 계층에서 이름으로 특정 JToken 검색

lovejava 2023. 3. 10. 20:57

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.7km"인 문자열입니다.

질문: NewtonsoftJson lib에 다음과 같은 내장 함수가 있습니까?

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

아니면 JObject의 모든 JToken 및 JAray에서 이름으로 JToken을 검색하는 재귀적 방법을 구현해야 합니까?

특정 토큰을 찾고 있으며 토큰에 대한 경로를 알고 있는 경우 내장된 토큰을 사용하여 쉽게 탐색할 수 있습니다.SelectToken()방법.예를 들어 다음과 같습니다.

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

JSON에서 지정된 이름의 토큰을 모두 찾아야 하는 경우 발생 위치에 관계없이 재귀적 방법이 필요합니다.다음은 도움이 될 수 있는 방법입니다.

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

다음은 데모입니다.

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

이것은 json 경로와 를 사용하여 매우 간단합니다.SelectTokens에 대한 방법.JToken이 방법은 매우 훌륭하며 다음과 같은 와일드 카드를 지원합니다.

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

발생 장소에 관계없이 속성의 모든 값을 원하는 경우 @brian-rogers에 의해 설명되는 재귀의 대체 방법을 다음에 나타냅니다.SelectToken@mhand의 제안대로:

모든 지속 시간 값을 가져옵니다.텍스트, 사용할 수 있습니다.SelectToken및 Linq:

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

상세정보: SelectToken을 사용한JSON 쿼리

언급URL : https://stackoverflow.com/questions/19645501/searching-for-a-specific-jtoken-by-name-in-a-jobject-hierarchy