Использование LINQ в JArray

#c# #json #linq #json.net

#c# #json #linq #json.net

Вопрос:

У меня есть JSON

 {
  "departments": [
    {
      "2": {"city": "Petersburg", "employees": "1200"}
    },
    {
      "1": {"city": "Ekaterinburg", "employees": "4000"}
    }
  ]
}
 

Как я могу получить значение города, если я знаю идентификатор, используя LINQ или что-то еще?

Я пытался

 var id = 2;
json["departments"].Single(x=>x.Name==id.ToString())["city"];
 

Но это не работает, я получаю ошибку компиляции:

 'JToken' does not contain a definition for 'Name' and no accessible extension method 'Name' accepting a first argument of type 'JToken' could be found (are you missing a using directive or an assembly reference?)
 

Демонстрационная скрипка здесь.

Ответ №1:

Ваш запрос LINQ может быть реализован следующим образом:

 var id = "2";
var city = (string)json["departments"]
    .Where(o => o[id] != null) // From the departments array, select the object where the required id property exists
    .Select(o => o[id]["city"]).SingleOrDefault(); // An extract the value of "city" from the nested object.
 

Или, что эквивалентно:

 var id = "2";
var city = (string)json["departments"]
    .SelectMany(i => i) // Use SelectMany() to project the properties of the array items to a flat enumerable 
    .Cast<JProperty>()  // Cast them to JProperty
    .Where(p => p.Name == id) // Now you can use Name
    .Select(p => p.Value["city"])
    .SingleOrDefault();
 

В качестве альтернативы, вы могли бы использовать SelectToken() для этой цели:

 var id = "2";
var path = $"departments[*].{id}.city"; // departments[*].2.city
var city = (string)json.SelectToken(path);
 

SelectToken() поддерживает синтаксис JSONPath и [*] является оператором подстановки JSONPath, указывающим, что следует искать все элементы массива.

Демонстрационная скрипка здесь.