Как сделать jobject из jobject?

У меня такой json:

{
   "Diagnoses": {
        "WESTERN EQUINE ENCEPHALITIS": {
            "ICD": "A83.1",
            "ID": "9"
        }
     },
   "ICD": {
        "A83.1": {
            "Name": "WESTERN EQUINE ENCEPHALITIS",
            "ID": "9"
        },
        "A83.2": {
            "Name": "EASTERN EQUINE ENCEPHALITIS",
            "ID": "10"
        }

     }
}

Мой настоящий json намного длиннее. В диагнозах и МКБ около 8000 наименований. Я пытаюсь найти лучший способ загрузить все ключи в список. Во-первых, у меня есть весь json в JObject. Чтобы внести это в список, я делаю следующее:

IList<JToken> jsonDiagName = jDiagnosis["Diagnoses"].Children().ToList();

foreach (JToken diagnosis in jsonDiagName)
            {
                cb_DiagName.Items.Add(diagnosis.ToObject<JProperty>().Name);
            }

Где jDiagnosis - это объект JObject. Однако, поскольку в json содержится около 9000 элементов, загрузка списка занимает около 3 минут. Поэтому я стал искать более эффективные способы сделать это и нашел это.

Однако, чтобы попробовать это предложение, мне нужно извлечь json из раздела «Диагностика», чтобы он стал собственным JObject. Итак, как я могу создать JObject из существующего JObject?

Спасибо

Вы можете попробовать десериализовать его в список

Ňɏssa Pøngjǣrdenlarp 26.10.2018 05:56
1
1
106
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Если вы имеете дело с большим объектом, как вы говорите, вы, вероятно, не хотите читать все сразу в памяти, вам следует использовать json-ридер.

Если вы хотите просто прочитать ключи корневого объекта, вы можете сделать это:

IEnumerable<string> GetKeys(string path)
{
    using (var reader = new JsonTextReader(File.OpenText(path)))
    {
        while (reader.Read())
        {
            switch (reader.TokenType)
            {
            case JsonToken.PropertyName:
                if ((string)reader.Value == "Diagnoses") // only interested in "Diagnoses" property
                {
                    foreach (var key in _GetKeys(reader))
                        yield return key;
                    yield break;
                }
                reader.Skip();
                break;
            }
        }
    }

    IEnumerable<string> _GetKeys(JsonReader reader)
    {
        while (reader.Read())
        {
            switch (reader.TokenType)
            {
            case JsonToken.PropertyName:
                yield return (string)reader.Value;
                reader.Skip(); // skip the value of the property
                break;
            case JsonToken.EndObject:
                yield break;
            }
        }
    }
}

Привет, спасибо за ответ. Вы предлагаете то, что я пытаюсь сделать. Однако я не хочу читать ключи корневого объекта, я хочу читать ключи дочернего объекта.

Sathya 26.10.2018 07:30

Вам придется изменить реализацию, чтобы искать желаемый объект и выводить ключи. Но идея та же.

Jeff Mercado 26.10.2018 07:58
Ответ принят как подходящий

Так что мне удалось решить эту проблему самому.

Я взял то, что предложил @New Contributer о десериализации JSON, но вместо этого я сериализовал JObject в строку, а затем проанализировал эту строку обратно в новый JObject.

string diags = JsonConvert.SerializeObject(jDiagnosis["Diagnoses"]);
JObject jDiags = JObject.Parse(diags);

string[] names = jDiags.Properties().Select(p => p.Name).ToArray();
cb_DiagName.Items.AddRange(names);

Не уверен, почему этот мыслительный процесс не пришел мне в голову раньше. : /

Другие вопросы по теме