C# найти JSON значение, основанное только на имени ключа через несколько уровней массива - PullRequest
1 голос
/ 28 апреля 2020

У меня есть различные входные данные JSON в формате, которые содержат определенное имя ключа terminalSize. Это единственная вещь, которую я знаю. Общее количество JSON деревьев или точная глубина terminalSize внутри JSON дерева навсегда останутся неизвестными и могут быть изменены.

Я ищу C# решение для l oop через каждого потомка строки JSON и найдите terminalSize, затем извлеките значение.

Я попробовал это с успехом, но он будет работать, только если terminalSize находится на первом уровне JSON:

var list = JsonConvert.DeserializeObject<List<Dictionary<string, string>>>(jsonString);
var dict = list.SelectMany(d => d).ToDictionary(p => p.Key, p => p.Value);
var terminal = dict["terminalSize"];

Пример 1.

{
  "status": "success",
  "data": {
    "terminalSize": 3766505.46,
    "totalTerminalSize": 3766505.46
  },
  "message": null
}

Пример 2.

{
  "lastUpdated": 1588020678,
  "terminalData": {
    "terminalSize": "451679852",
    "totalTerminalSize": "2100000000"
  },
  "terminalValueSeries": {
    "8x7": 2.33,
    "8x6": 3.73,
    "8x5": 4.49,
    "8x4": 3.68,
    "8x3": 13998,
    "8x2": 274936,
    "8x1": 5.09
  }
}

Пример 3.

{
  "terminalSize": "492612346.17",
  "terminalStatus": "online"
}

Ответы [ 3 ]

3 голосов
/ 28 апреля 2020

Вы также можете использовать linq и фильтровать коллекцию JProperty на основе JProperty.Name. Например

var result = JObject.Parse(jsonString)
                    .DescendantsAndSelf()
                    .OfType<JProperty>()
                    .Single(x=>x.Name.Equals("terminalSize"))
                    .Value;
2 голосов
/ 28 апреля 2020

Вы можете проанализировать JSON для JToken, затем использовать SelectToken с рекурсивным спуском JsonPath оператор .., чтобы получить terminalSize в любом месте JSON:

var terminalSize = (double?) JToken.Parse(json).SelectToken("$..terminalSize");

Fiddle: https://dotnetfiddle.net/5ziYbP

Если в * 1031 может быть несколько terminalSize клавиш *, например, если у вас есть массив терминалов, вы можете использовать вместо него SelectTokens и поместить размеры терминалов в Dictionary с ключом по пути:

var sizes = JToken.Parse(json4)
                  .SelectTokens("$..terminalSize")
                  .ToDictionary(t => t.Path, t => (double)t);

Fiddle: https://dotnetfiddle.net/ivSM88

2 голосов
/ 28 апреля 2020

Вы можете проанализировать JSON в JObject, а затем рекурсивно go через все свойства и подобъекты, чтобы найти значение terminalSize. Нет необходимости десериализовать весь JSON в специфицированный c объект

var json = JObject.Parse(jsonString);
var result = GetTerminalSize(json);

double GetTerminalSize(JObject input)
{
    foreach (var property in input.Properties())
    {
        if (property.Name == "terminalSize")
            return property.Value.Value<double>();

        if (property.Value.Type == JTokenType.Object)
            return GetTerminalSize((JObject) property.Value);

        //not sure, if the is a need to handle an array
        if (property.Value.Type == JTokenType.Array)
            foreach (var item in (JArray) property.Value)
                return GetTerminalSize((JObject) item);
    }

    return 0;
}

. Он возвращает правильное значение для всех прикрепленных образцов

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...