1. Вспоминаем JSON
JSON расшифровывается как JavaScript Object Notation. Несмотря на зловещее слово JavaScript в названии, формат этот абсолютно языконейтральный и дружелюбный ко всем (ну почти ко всем) языкам программирования, включая C#. Его придумали для того, чтобы удобно и понятно описывать данные — объекты, массивы, списки и словари — в виде обычного текста.
В современном мире, где почти каждая программа общается с другими программами, JSON стал фактически стандартом де-факто для сериализации и обмена структурированными данными. Он используется повсюду: от REST API до хранения пользовательских настроек и даже для внутреннего взаимодействия между микросервисами. И есть веская причина — он читаем человеком (если человек не боится фигурных скобок), прост в парсинге и поддерживается всеми современными языками и библиотеками.
Почему не XML?
JSON проще, короче и легче читается, чем XML. К тому же, он без лишнего шума и тегов, более логично ложится на структуры данных большинства языков программирования. А ещё с ним не нужно возиться с закрывающими тегами, кавычками и прочей XML-бюрократией. Короче — JSON это про быстрее, проще, удобнее.
2. Основные элементы синтаксиса JSON
Представим, что JSON — это простое дерево (или матрёшка), состоящее из объектов, массивов и элементарных данных. Вот какие «кирпичики» в нашем распоряжении:
Объекты (Objects)
Объект JSON — это набор пар «ключ: значение», окружённый фигурными скобками { }.
Пример:
{
"name": "Alice",
"age": 23
}
В C# такую структуру можно представить в виде класса или словаря.
Массивы (Arrays)
Массив JSON — это упорядоченный список элементов (значений любого типа), заключённый в квадратные скобки [ ].
Пример:
[1, 2, 3, 42]
Или так:
[
{"name": "Ivan"},
{"name": "Olga"}
]
В C# — это List<T>, T[] и аналогичные коллекции.
Пары «ключ-значение»
Ключи всегда строки (в двойных кавычках!), а значения могут быть любых типов данных, разрешённых в JSON.
Пример:
{
"id": 123,
"login": "student",
"isActive": true
}
Типы данных в JSON
| Тип JSON | Пример | Описание |
|---|---|---|
| Число (Number) | |
Целое или дробное число |
| Строка (String) | |
Всегда в двойных кавычках |
| Булево (Boolean) | |
Логическое значение |
| null | |
Отсутствие значения |
| Объект (Object) | |
Словарь или сущность с полями |
| Массив (Array) | |
Последовательность значений |
Пример — всё вместе:
{
"id": 1,
"name": "Bob",
"scores": [10, 20, 30],
"profile": {
"email": "bob@mail.com",
"phone": null
},
"isAdmin": false
}
Видите, как компактно и логично можно описать целый объект пользователя.
3. Правила оформления JSON
Строки всегда в двойных кавычках
Даже если очень хочется поставить одинарные, JSON этого не простит. Вот так — правильно:
{ "name": "Vera" }
Вот так — ошибка:
{ 'name': 'Vera' }
Ключи — только строки
В отличие от C#, где ключ словаря может быть хоть int, хоть enum, в JSON ключ — это всегда строка:
{ "2025": "Год C#", "favorite": true }
Никаких хвостовых запятых
В отличие от C# массивов и объектов, лишняя запятая перед закрывающей скобкой — это синтаксическая ошибка JSON!
// ОШИБКА! (последняя запятая не допускается)
{
"id": 10,
"name": "Oleg",
}
Правильно:
{
"id": 10,
"name": "Oleg"
}
Пробелы и переносы строк
Их можно ставить для красоты, парсеры их игнорируют. Обычно для формата «для людей» используют pretty-printed (отформатированный) JSON, для передачи по сети — minified (в одну строку, без пробелов).
4. Как C# объекты преобразуются в JSON
Если вы сериализуете объект с помощью System.Text.Json.JsonSerializer.Serialize(), то поля и свойства объекта превращаются в пары «ключ-значение».
Пример C# класса и сериализации
public class Book
{
public string Title { get; set; }
public int Pages { get; set; }
}
var book = new Book { Title = "CLR via C#", Pages = 900 };
string json = JsonSerializer.Serialize(book);
Console.WriteLine(json); // {"Title":"CLR via C#","Pages":900}
Коллекции
- List<int> превращается в [1,2,3]
- string[] превращается в ["hi", "wow"]
- List<Person> — в массив объектов
Словари
Словарь вида Dictionary<string, int> превращается в объект:
var dict = new Dictionary<string, int>
{
["apples"] = 5, ["bananas"] = 10
};
string json = JsonSerializer.Serialize(dict);
// {"apples":5,"bananas":10}
5. Визуальная схема: как строится JSON
Вложенность — как матрешка
Объект
│
├── Пара: "name": "Alex"
├── Пара: "hobbies": массив
│ │
│ ├── "skiing"
│ └── "programming"
└── Пара: "profile": объект
│
├── "age": 42
└── "city": "Базель"
В результате:
{
"name": "Alex",
"hobbies": ["skiing", "programming"],
"profile": {
"age": 42,
"city": "Базель"
}
}
6. Типичные ошибки и особенности синтаксиса
В программировании не бывает идеального мира — даже в JSON есть свои ловушки! Если вы попытаетесь отправить JSON с неправильными кавычками, с лишними запятыми или с ключами, не обернутыми в кавычки — парсер выдаст ошибку.
Ещё одна «подстава» — числа с ведущими нулями. В JSON это запрещено (например, 0123 — ошибка).
Полезно знать: Некоторые парсеры (например, JavaScript-ный JSON.parse) более лояльны и могут «простить» небольшие нарушения. Но большинство «суровых» парсеров (например, в C# и .NET) будут жаловаться на малейшее нарушение синтаксиса.
7. Примеры преобразования C# данных в JSON
Давайте попробуем сериализовать сложную структуру на практике. Наше учебное приложение развивается: допустим, у нас теперь есть список студентов, и мы хотим их сохранить в файл JSON.
Определим класс:
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
}
Заполним список:
var students = new List<Student>
{
new Student { Name = "Анна", Age = 20 },
new Student { Name = "Никита", Age = 22 }
};
Сериализация:
using System.Text.Json;
// Сериализуем список студентов в строку JSON
string json = JsonSerializer.Serialize(students, new JsonSerializerOptions { WriteIndented = true });
Console.WriteLine(json);
/*
[
{
"Name": "Анна",
"Age": 20
},
{
"Name": "Никита",
"Age": 22
}
]
*/
Видите, как удобно? Каждый студент — это отдельный объект внутри JSON-массива.
8. Мини-генератор: как «руками» написать JSON
Иногда приходится писать JSON самому, например — создавать тестовые данные вручную. Вот чек-лист:
- Внешние фигурные скобки — для объекта, внешние квадратные — для массива.
- Ключ всегда — строка в двойных кавычках.
- Значения — строки (в двойных кавычках), числа, true, false, null, объект ({}), массив ([]).
- Только запятые между элементами, не после последнего!
- Отступы и пробелы для читабельности (но не обязательны).
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ