JSON обработка в TypeScript: полное руководство с примерами

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

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 — популярная библиотека для валидации, часто

Рекомендаций