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

R. Akhmetov

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

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

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

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

3 ответа

R. Akhmetov

Подготовка

Давайте разберемся, что из себя вообще представляет ваш 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);
    </dictionary<string,>

Поясню, мы вызываем метод 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);
}
</dictionary<string,></string,>

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


R. Akhmetov

Как вам уже предложили в комментариях к вопросу, если вам нужен ассоциативный массив - его и используйте. Самый популярный сериализатор - 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);
</dictionary<string,>


R. Akhmetov

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

licensed under cc by-sa 3.0 with attribution.