[Json.Net] SelectToken/SelectTokens 사용법

 종종 가변적인 구조의 JSON 데이터를 C#에서 다뤄야 할 경우나 혹은 JSON내의 특정 데이터만 추출 혹은 수정을 원할경우 일일이 맵핑할 class들을 만들어서 JSON 데이터를 다루기보다 JObject로 parsing 후 아래와 같이 SelectToken/SelectTokes 함수들을 사용해서 원하는 token을 찾아서 값을 가져오거나 조작하는 것이 훨씬 효율적입니다.

 

원문: https://www.newtonsoft.com/json/help/html/SelectToken.htm

 

1. SelectToken

 SelectToken은 JToken을 리턴하는 method이며 하위 토큰에 대한 문자열 경로를 사용합니다. SelectToken은 하위 토큰을 반환하거나 경로 위치에서 토큰을 찾을 수 없는 경우 null 참조를 반환합니다.
경로는 마침표로 구분된 속성 이름과 배열 인덱스로 구성됩니다. 예) Manufacturers[0].Name.

JObject o = JObject.Parse(@"{
  'Stores': [
    'Lambton Quay',
    'Willis Street'
  ],
  'Manufacturers': [
    {
      'Name': 'Acme Co',
      'Products': [
        {
          'Name': 'Anvil',
          'Price': 50
        }
      ]
    },
    {
      'Name': 'Contoso',
      'Products': [
        {
          'Name': 'Elbow Grease',
          'Price': 99.95
        },
        {
          'Name': 'Headlight Fluid',
          'Price': 4
        }
      ]
    }
  ]
}");

string name = (string)o.SelectToken("Manufacturers[0].Name");
// Acme Co

decimal productPrice = (decimal)o.SelectToken("Manufacturers[0].Products[0].Price");
// 50

string productName = (string)o.SelectToken("Manufacturers[1].Products[0].Name");
// Elbow Grease

 

2. SelectToken with JSONPath

JSONPath(https://goessner.net/articles/JsonPath/) 표현식을 이용해서 token을 가져올 수 있습니다.

JObject o = JObject.Parse(@"{
  'Stores': [
    'Lambton Quay',
    'Willis Street'
  ],
  'Manufacturers': [
    {
      'Name': 'Acme Co',
      'Products': [
        {
          'Name': 'Anvil',
          'Price': 50
        }
      ]
    },
    {
      'Name': 'Contoso',
      'Products': [
        {
          'Name': 'Elbow Grease',
          'Price': 99.95
        },
        {
          'Name': 'Headlight Fluid',
          'Price': 4
        }
      ]
    }
  ]
}");

// manufacturer with the name 'Acme Co'
JToken acme = o.SelectToken("$.Manufacturers[?(@.Name == 'Acme Co')]");

Console.WriteLine(acme);
// { "Name": "Acme Co", Products: [{ "Name": "Anvil", "Price": 50 }] }

// name of all products priced 50 and above
IEnumerable<JToken> pricyProducts = o.SelectTokens("$..Products[?(@.Price >= 50)].Name");

foreach (JToken item in pricyProducts)
{
    Console.WriteLine(item);
}
// Anvil
// Elbow Grease

 

 

3. SelectToken with LINQ

SelectToken 함수와 표준 LINQ 함수를 함께 사용해서 Token를 가져올 수 있습니다.

IList<string> storeNames = o.SelectToken("Stores").Select(s => (string)s).ToList();
// Lambton Quay
// Willis Street

IList<string> firstProductNames = o["Manufacturers"].Select(m => (string)m.SelectToken("Products[1].Name")).ToList();
// null
// Headlight Fluid

decimal totalPrice = o["Manufacturers"].Sum(m => (decimal)m.SelectToken("Products[0].Price"));
// 149.95