C# Json.Net - Как десериализовать массив объектов, содержащий массив других объектов

Данные Json, полученные с http-сервера, выглядят следующим образом:

[
   {
      "token":"NlhYnzF0xqG"
   },
   [
      {
         "ts":"2019-03-21 14:06:22.123",
         "id":"CC_RTC_Second",
         "val":"22"
      },
      {
         "ts":"2019-03-21 14:06:00.096",
         "id":"CC_RTC_Minute",
         "val":"6"
      },
      {
         "ts":"2019-03-21 14:00:00.276",
         "id":"CC_RTC_Hour",
         "val":"14"
      }
   ]
]

Я попробовал некоторые методы, представленные в документации Newtonsoft.Json, но не смог найти правильный путь. Я провел два дня, тестируя решения из ответов StackOverflow, но безуспешно.

Какие типы и методы С# следует использовать в этом конкретном случае?

Структура данных может варьироваться:
полный список атрибутов: td, id, val, flags, type, uts, nr.
Все они струны.
Сервер может опустить атрибуты, если они не существуют, поэтому, например, я могу получить только ts + id.
Есть ли способ, как работать с такими данными?

Объявите классы для хранения ваших свойств, а затем десериализуйте их. Ваш вопрос не ясен, можете ли вы показать нам, что вы пробовали?

Lasse V. Karlsen 22.03.2019 12:05

Скорее всего, вам понадобится собственный десериализатор, иначе вы получите объекты/динамические типы из-за того, что у вас есть массив, содержащий 1 объект, а затем 1 массив, поэтому вы не можете создать List<T>, здесь, потому что у вас есть разные T для разных элементов.

Lasse V. Karlsen 22.03.2019 12:07

При работе только с одним объектом ts+id+val я могу использовать:

trapper66 22.03.2019 12:12

Вы можете использовать JsonConvert.DeserializeObject<JToken>(json).Select(token => token is JArray ? (object)token.ToObject<List<Other>>() : (object)token.ToObject<TokenData>()), замените на правильные типы.

Lasse V. Karlsen 22.03.2019 12:14

При работе только с одним объектом ts+id+val я могу использовать: Dictionary<string, string> dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(json). Затем я попытался использовать класс и вызвать JsonConvert.DeserializeObject<MyClass>(json). Класс выглядел так: открытый класс MyClass {токен открытой строки {get; набор;} общедоступные данные IEnumerable<IDictionary<string,string>> {get; задавать;}}. Теперь понимаю, что так нельзя :(

trapper66 22.03.2019 12:18
JsonConvert.DeserializeObject<List<dictionary<string,string>‌​>>(your JSON Data Object gos here)
bilpor 22.03.2019 12:56
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
7
842
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Прежде всего, ваш json довольно сложен, и его утомительная работа по созданию иерархии классов для вашего json,

Но один простой подход заключается в том, что если вы разберете свой JSON в JArray, а затем возьмете

  • 0-й элемент в один класс
  • А все остальное в список другого класса

Тогда, возможно, вы сможете получить все свои данные json

string json = File.ReadAllText(@"Path to your json");

JArray jArray = JArray.Parse(json);

Token token = jArray[0].ToObject<Token>();
jArray.RemoveAt(0);
RandomData[] tokenData = jArray.First.ToObject<RandomData[]>();

//--------------------Print Data to Console-------------------

Console.WriteLine(token.token + "\n");

foreach (var item in tokenData)
{
    Console.WriteLine("ts: " + item.ts);
    Console.WriteLine("id: " + item.id);
    Console.WriteLine("val: " + item.val + "\n");
}

Console.ReadLine();

И занятия есть,

class Token
{
    public string token { get; set; }
}

class RandomData
{
    public string ts { get; set; }
    public string td { get; set; }
    public string id { get; set; }
    public string val { get; set; }
    public string flags { get; set; }
    public string type { get; set; }
    public string uts { get; set; }
    public string nr { get; set; }
}

Выход:

Примечание: Вам необходимо установить пакет NuGet НьютонСофт и импортировать пространство имен using Newtonsoft.Json.Linq; в вашу программу.

Ваш ответ полностью решает мою проблему. Спасибо :)

trapper66 24.03.2019 19:29

Есть моя версия ответа:

var strData = @"[{
         'token': 'NlhYnzF0xqG'
       },
       [{
         'ts': '2019-03-21 14:06:22.123',
         'id': 'CC_RTC_Second',
         'val': '22'
       }, {
         'ts': '2019-03-21 14:06:00.096',
         'id': 'CC_RTC_Minute',

       }, {

         'id': 'CC_RTC_Hour',
         'val': '14'
       }]
     ]";   
        var result = JsonConvert.DeserializeObject<List<JToken>>(strData);
        var tokens = result.Where( x=> x.Type == JTokenType.Object).Select(x=> x.ToObject<Token>());
        var innerData = result.Where(x => x.Type == JTokenType.Array).Select(x => x.ToObject<List<InnerData>>());

есть классы:

 public class Token
        {
             public string token { set; get; }
        }
    public class InnerData
        {
            public string ts { set; get; }
            public string id { set; get; }
            public string val { set; get; }    
        }

Вы можете распечатать результаты, как упоминалось ранее:

foreach (var token in tokens)
{
    Console.WriteLine("ts: " + token.token);
}

Спасибо за ответ, но я боюсь, что не смогу использовать полученные вары. Запросы для меня новые, и я не знаю, как вывести данные, содержащиеся в токенах и innerData. Я был бы признателен за вашу помощь.

trapper66 24.03.2019 19:48

вы можете распечатать результаты linq, как упоминалось ранее. Я добавил это, чтобы опубликовать ответ

Oleg Bondarenko 24.03.2019 19:51

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