JSON обработка в TypeScript: от базовых операций до продвинутой типизации
JSON (JavaScript Object Notation) остаётся основным форматом обмена данными в веб-разработке. TypeScript, будучи строго типизированным надмножеством JavaScript, предоставляет мощные инструменты для безопасной и эффективной работы с JSON. В этой статье мы разберём все аспекты обработки JSON в TypeScript: от простого парсинга до сложной валидации с помощью дженериков и сторонних библиотек.
1. Базовые операции: парсинг и сериализация
TypeScript полностью наследует встроенные методы JavaScript для работы с JSON: JSON.parse() и JSON.stringify(). Однако их использование в TypeScript требует особого внимания к типам.
Парсинг JSON строки
// Простой парсинг — результат any
const rawData = JSON.parse('{"name": "Alice", "age": 30}');
// rawData имеет тип any — теряем все преимущества TypeScript
// Правильный подход: указать ожидаемый тип через дженерик
interface User {
name: string;
age: number;
}
const user: User = JSON.parse('{"name": "Alice", "age": 30}');
// user теперь типизирован, но TypeScript не проверяет соответствие на этапе выполнения
Важно: JSON.parse() не проверяет, соответствует ли переданная строка указанному интерфейсу. Это может привести к ошибкам во время выполнения. Для надёжной валидации используйте дополнительные инструменты.
Сериализация объектов в JSON
const user: User = { name: "Bob", age: 25 };
const jsonString = JSON.stringify(user);
// Результат: '{"name":"Bob","age":25}'
// Кастомная сериализация с replacer
const filteredJson = JSON.stringify(user, ['name']);
// Результат: '{"name":"Bob"}'
// Форматирование с отступами
const prettyJson = JSON.stringify(user, null, 2);
/* Результат:
{
"name": "Bob",
"age": 25
}
*/
2. Типизация JSON данных: интерфейсы и типы
Правильная типизация — ключевое преимущество TypeScript при работе с JSON. Рассмотрим основные подходы.
Интерфейсы для структур данных
interface ApiResponse<T> {
status: 'success' | 'error';
data: T;
message?: string;
timestamp: number;
}
interface Product {
id: string;
title: string;
price: number;
tags: string[];
inStock: boolean;
}
// Использование дженерика для типизации ответа API
type ProductResponse = ApiResponse<Product>;
const response: ProductResponse = {
status: 'success',
data: {
id: 'prod-123',
title: 'Wireless Mouse',
price: 29.99,
tags: ['electronics', 'accessories'],
inStock: true
},
timestamp: Date.now()
};
Типы для динамических JSON структур
// Для объектов с неизвестными ключами
type DynamicObject = Record<string, unknown>;
// Для строго типизированных словарей
interface Config {
[key: string]: string | number | boolean;
}
// Union типы для полиморфных JSON
type Shape =
| { kind: 'circle'; radius: number }
| { kind: 'rectangle'; width: number; height: number }
| { kind: 'triangle'; base: number; height: number };
function calculateArea(shape: Shape): number {
switch (shape.kind) {
case 'circle': return Math.PI * shape.radius ** 2;
case 'rectangle': return shape.width * shape.height;
case 'triangle': return (shape.base * shape.height) / 2;
}
}
3. Валидация JSON данных: runtime проверки
TypeScript проверяет типы только на этапе компиляции. Для runtime-валидации JSON данных (например, из внешнего API) используйте специализированные библиотеки.
Использование Zod для декларативной валидации
import { z } from 'zod';
// Определяем схему
const UserSchema = z.object({
name: z.string().min(2).max(50),
age: z.number().int().positive().max(120),
email: z.string().email(),
role: z.enum(['admin', 'user', 'guest'])
});
// Тип автоматически выводится из схемы
type UserType = z.infer<typeof UserSchema>;
// Безопасный парсинг
function parseUser(data: unknown): UserType {
const result = UserSchema.safeParse(data);
if (!result.success) {
console.error('Validation errors:', result.error.flatten());
throw new Error('Invalid user data');
}
return result.data;
}
// Использование
const rawJson = '{"name":"John","age":30,"email":"john@example.com","role":"admin"}';
const user = parseUser(JSON.parse(rawJson));
// user теперь имеет правильный тип UserType
Альтернативы: Yup и io-ts
- Yup — популярная библиотека для валидации, часто