Введение: Почему JSON и TypeScript — идеальная пара
В современной веб-разработке JSON (JavaScript Object Notation) стал универсальным форматом для обмена данными между клиентом и сервером, хранения конфигураций и передачи информации в API. TypeScript, как надстройка над JavaScript, добавляет к этой гибкости мощную систему типов, делая работу с JSON не только удобной, но и безопасной. В этой статье мы разберём, как правильно парсить (преобразовывать строку JSON в объект) и сериализовывать (преобразовывать объект в строку JSON) данные, используя TypeScript. Материал рассчитан на начинающих разработчиков, которые уже знакомы с основами TypeScript, но хотят уверенно работать с JSON.
Что вы узнаете
- Как использовать встроенные методы
JSON.parse()иJSON.stringify(). - Как типизировать данные при парсинге для предотвращения ошибок.
- Как обрабатывать исключения и проверять корректность JSON.
- Практические примеры с реальными сценариями.
1. Основы: Методы JSON.parse() и JSON.stringify()
TypeScript наследует от JavaScript два глобальных метода для работы с JSON. Они доступны без импорта дополнительных библиотек.
1.1. Парсинг JSON в объект: JSON.parse()
Метод JSON.parse() принимает строку в формате JSON и возвращает объект JavaScript (или массив, число, строку). В TypeScript мы можем указать ожидаемый тип результата с помощью дженериков.
// Простой пример без типизации
const jsonString = '{"name": "Алиса", "age": 30}';
const user = JSON.parse(jsonString);
console.log(user.name); // "Алиса"
1.2. Сериализация объекта в JSON: JSON.stringify()
Метод JSON.stringify() преобразует объект или значение JavaScript в строку JSON. Он автоматически обрабатывает все примитивные типы, массивы и простые объекты.
const user = {
name: "Боб",
age: 25,
isAdmin: false
};
const jsonString = JSON.stringify(user);
console.log(jsonString); // '{"name":"Боб","age":25,"isAdmin":false}'
2. Типизация данных при парсинге JSON в TypeScript
Главное преимущество TypeScript — возможность задать тип для результата парсинга. Это защищает код от ошибок во время компиляции и делает его самодокументируемым.
2.1. Использование интерфейсов и дженериков
Создайте интерфейс, описывающий структуру ваших данных, и передайте его в JSON.parse() как дженерик:
interface User {
id: number;
name: string;
email: string;
isActive: boolean;
}
const jsonData = '{"id": 1, "name": "Виктор", "email": "victor@example.com", "isActive": true}';
const user: User = JSON.parse(jsonData);
console.log(user.email); // "victor@example.com"
// user.id теперь строго number
2.2. Обработка вложенных объектов и массивов
Интерфейсы отлично работают со сложными структурами:
interface Address {
city: string;
zip: string;
}
interface Employee {
id: number;
name: string;
address: Address;
skills: string[];
}
const employeeJson = '{"id": 101, "name": "Елена", "address": {"city": "Москва", "zip": "101000"}, "skills": ["TS", "JS", "Python"]}';
const employee: Employee = JSON.parse(employeeJson);
console.log(employee.address.city); // "Москва"
2.3. Что будет, если тип не совпадает?
Важно понимать: TypeScript проверяет типы только на этапе компиляции. Если в рантайме придет JSON с другой структурой (например, age будет строкой вместо числа), ошибка возникнет в коде, но не в JSON.parse(). Для полной безопасности используйте runtime-валидаторы (например, Zod или io-ts), но для большинства учебных проектов достаточно интерфейсов.
3. Сериализация: тонкости и кастомные преобразования
Метод JSON.stringify() также можно настраивать с помощью параметров replacer и space.
3.1. Форматирование вывода с параметром space
Параметр space добавляет отступы для читаемости. Он принимает число (количество пробелов) или строку (например, "\t" для табуляции).
const data = { name: "Ольга", age: 28, city: "СПб" };
console.log(JSON.stringify(data, null, 2));
/* Вывод:
{
"name": "Ольга",
"age": 28,
"city": "СПб"
}
*/
3.2. Фильтрация данных с помощью replacer
Параметр replacer может быть функцией или массивом строк. Он определяет, какие свойства включать в итоговую строку.
const user = {
id: 1,
username: "ivan_petrov",
password: "secret123",
email: "ivan@example.com"
};
// Исключаем пароль
const safeUser = JSON.stringify(user, ["id", "username", "email"]);
console.log(safeUser); // '{"id":1,"username":"ivan_petrov","email":"ivan@example.com"}'
3.3. Обработка специальных значений
JSON.stringify() игнорирует функции, undefined, Symbol и преобразует NaN / Infinity в null. Если вам нужно сохранить такие значения, используйте кастомный replacer.
const obj = {
value: undefined,
func: () => console.log("test"),
num: NaN
};
console.log(JSON.stringify(obj)); // '{"num":null}'
4. Обработка ошибок и проверка корректности JSON
При работе с внешними данными (из API, файлов, пользовательского ввода) всегда есть риск получить некорректный JSON. Всегда оборачивайте JSON.parse() в try...catch.
4.1. Базовый перехват ошибок
function safeParse(jsonString: string): any {
try {
return JSON.parse(jsonString);
} catch (error) {
console.error("Ошибка парсинга JSON