Как распарсить json в ассоциативный массив / C#

316
28 мая 2018, 10:40

Есть ответ с сервера в виде json:

{
  "14.05.2018": {
    "Min": "2",
    "Max": "7"
  },
  "15.05.2018": {
    "Min": "1",
    "Max": "7"
  }
} 

Нужно распарсить в C# по уму. Я так понимаю это двумерный ассоциативный массив.

Подскажите как быть. Сам новичок в этом деле и ранее с json не работал.

Answer 1

Подготовка

Давайте разберемся, что из себя вообще представляет ваш JSON. Я лично для подобных целей использую данный ресурс. Вставляем туда наши данные и видим следующую картину:

Что тут у нас?

  • У нас есть первый уровень (назовем его Root).
    • Root содержит в себе некие объекты, которые имеют название и что то внутри, (внутренние объекты назовем к примеру Data) .
      • Внутри Data мы видим два значения (min и max).

Хорошо, со структурой разобрались, дальше нам понадобится то, что облегчит нам жизнь при работе с JSON форматом, я лично рекомендую использовать Newtonsoft.Json, отличная библиотека для работы с JSON!

Десериализация

Разобравшись со структурой и установив необходимое, можно приступать к десериализации (преобразования JSON в объект).

  • Пойдем с самого конца, а именно создадим для начала Data. Мы помним, что Data имеет в себе 2 значения min и max, оба содержат число (то есть int). Имея все это, мы можем написать следующий класс:

    public class Data
    {
        public int Min { get; set; }
        public int Max { get; set; }
    }
    

Заметьте, все переменные здесь написаны по правилам CamelCase, то есть с большой буквы. Советую и вам придерживаться этого стиля при написании подобных классов, но нужно помнить: поменять регистр в названии можно без проблем, но если имя в классе будет отличаться от того, что в JSON — мы не получим данные и по этому подобные переименования стоит помечать атрибутом [JsonProperty("oldName")] с указанием имени, который есть в JSON.

  • Так, имея класс Data, мы можем пойти уровнем выше, создать объект с именем и Data внутри. Для этого в C# принято использовать Dictionary (словарь), где Key — это будет имя (в вашем случае дата), а Value — данные (в вашем случае — класс Data). Исходя из этого мы можем написать следующее:

    var source = "{\"14.05.2018\":{\"min\":\"2\",\"max\":\"7\"},\"15.05.2018\":{\"min\":\"1\",\"max\":\"7\"}}";
    var parsed = JsonConvert.DeserializeObject<Dictionary<string, Data>>(source);
    

Поясню, мы вызываем метод DeserializeObject, которому задаем тип данных Dictionary<string, Data>, ну и передаем source — наш JSON в виде string.

Собственно и все, результатом мы получим объект Dictionary<string, Data> из которого можно получить то, что нам нужно, к примеру так:

parsed["14.05.2018"].Max;

Или пройтись циклом:

foreach (var data in parsed)
{
    Console.WriteLine($"Key: {data.Key}");
    Console.WriteLine($"Max: {data.Value.Max} Min: {data.Value.Min}");
}

Сам же объект parsed будем иметь примерно следующую структуру:

Кстати! Для работы с JSON очень круто помогают ресурсы, которые сами за вас составляют нужную структуру классов, к примеру этот. Вставив ваш JSON в левое поле и указав в поле Name желаемое имя класса (Data), сайт составит нам следующую структуру:

public partial class Data
{
    [JsonProperty("min")]
    public string Min { get; set; }
    [JsonProperty("max")]
    public string Max { get; set; }
}
public partial class Data
{
    public static Dictionary<string, Data> FromJson(string json) => JsonConvert.DeserializeObject<Dictionary<string, Data>>(json, QuickType.Converter.Settings);
}

Не напоминает ничего? В общем пользуйтесь, вещь очень полезная!
Надеюсь помог. Удачи в изучении C#!

Answer 2

Как вам уже предложили в комментариях к вопросу, если вам нужен ассоциативный массив - его и используйте. Самый популярный сериализатор - JSON.NET - вполне его поддерживает.

Вам нужно получить Dictionary<string, Range>, где Range:

// переименовать по желанию
public class Range
{
    public string Min { get; set; }
    public string Max { get; set; }
}

Десериализация:

var deserialized = JsonConvert.DeserializeObject<Dictionary<string, Range>>(jsonString);
Answer 3

Рискну предложить рукописный вариант конвертора, они не очень сложные в доработке под свои задачи, вот пример такого конвертера с возможностью задавать формат исходника json с помощью атрибутов. Буду рад если мой ответ поможет вам выбрать оптимальное решение.

READ ALSO
Вызов командной строки в папке

Вызов командной строки в папке

Имеется следующий код:

230
Как получить ConnectionString из DbContext&#39;а EF Core?

Как получить ConnectionString из DbContext'а EF Core?

Это краткий перевод вопроса How to get ConnectionString from EF7 DbContext

286
Делегирование свойств в C#

Делегирование свойств в C#

Допустим, есть класс с неким свойством:

256
Как создавать объект по нажатию кнопки

Как создавать объект по нажатию кнопки

Как заставить прописанный мной объект для игры, создаваться только после нажатие игроком на кнопку 'Играть'Я не смог разобраться в instance, а opacity...

222