Работа с JSON в TypeScript: парсинг и сериализация данных

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

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

Начать курс

Введение в работу с JSON в TypeScript

JSON (JavaScript Object Notation) остаётся одним из самых популярных форматов для обмена данными между клиентом и сервером. В TypeScript, который является строго типизированной надстройкой над JavaScript, работа с JSON требует особого внимания к типам данных. В этой статье мы подробно разберём, как правильно парсить и сериализовать JSON в TypeScript, избегая типичных ошибок и используя преимущества статической типизации.

TypeScript предоставляет все встроенные методы JavaScript для работы с JSON, но добавляет к ним мощную систему типов. Это позволяет создавать более надёжный и предсказуемый код. Мы рассмотрим как базовые операции, так и продвинутые техники, включая кастомные функции-валидаторы и работу с дженериками.

Основы парсинга JSON: JSON.parse()

Метод JSON.parse() преобразует строку JSON в объект JavaScript. В TypeScript важно правильно типизировать результат, чтобы компилятор мог проверять корректность обращений к свойствам объекта.

Базовый синтаксис и типизация

Рассмотрим простой пример:

const jsonString = '{"name": "Анна", "age": 30, "city": "Москва"}';
const user = JSON.parse(jsonString);
console.log(user.name); // Анна

Проблема в том, что TypeScript не знает структуру объекта user. Переменная имеет тип any, что лишает нас всех преимуществ типизации. Правильное решение — явно указать тип:

interface User {
  name: string;
  age: number;
  city: string;
}

const jsonString = '{"name": "Анна", "age": 30, "city": "Москва"}';
const user: User = JSON.parse(jsonString); // Ошибка!
// Type 'any' is not assignable to type 'User'.

TypeScript выдаст ошибку, потому что JSON.parse() возвращает any, а мы пытаемся присвоить его типизированной переменной. Используйте приведение типа:

const user = JSON.parse(jsonString) as User;
console.log(user.name.toUpperCase()); // АННА

Безопасный парсинг с проверкой типов

Приведение типа as — это быстрое решение, но оно не гарантирует, что данные действительно соответствуют ожидаемой структуре. Для production-кода рекомендуется создавать функции-валидаторы:

function parseUser(data: string): User | null {
  try {
    const parsed = JSON.parse(data);
    if (typeof parsed === 'object' && parsed !== null &&
        typeof parsed.name === 'string' &&
        typeof parsed.age === 'number' &&
        typeof parsed.city === 'string') {
      return parsed as User;
    }
    return null;
  } catch {
    return null;
  }
}

const user = parseUser('{"name": "Иван", "age": 25, "city": "СПб"}');
if (user) {
  console.log(`Пользователь: ${user.name}, возраст: ${user.age}`);
}

Такой подход предотвращает ошибки времени выполнения, если сервер вернёт некорректные данные.

Сериализация: JSON.stringify()

Метод JSON.stringify() преобразует объект JavaScript в строку JSON. В TypeScript этот метод работает так же, как в JavaScript, но с учётом типов.

Простая сериализация

const user: User = {
  name: 'Мария',
  age: 28,
  city: 'Казань'
};

const jsonString = JSON.stringify(user);
console.log(jsonString); // {"name":"Мария","age":28,"city":"Казань"}

Параметры форматирования

Для читаемого вывода используйте параметры replacer и space:

const user = {
  name: 'Алексей',
  age: 35,
  city: 'Новосибирск',
  password: 'secret123'
};

// Исключаем поле password
const jsonString = JSON.stringify(user, ['name', 'age', 'city'], 2);
console.log(jsonString);
/* Вывод:
{
  "name": "Алексей",
  "age": 35,
  "city": "Новосибирск"
}
*/

Параметр replacer может быть функцией для более гибкой фильтрации:

const jsonString = JSON.stringify(user, (key, value) => {
  if (key === 'password') return undefined; // исключаем
  return value;
}, 2);

Сериализация вложенных объектов и массивов

interface Company {
  name: string;
  employees: User[];
}

const company: Company = {
  name: 'TechCorp',
  employees: [
    { name: 'Ольга', age: 32, city: 'Екатеринбург' },
    { name: 'Дмитрий', age: 29, city: 'Ростов' }
  ]
};

const jsonString = JSON.stringify(company, null, 2);
console.log(jsonString);
/* Вывод:
{
  "name": "TechCorp",
  "employees": [
    {
      "name": "Ольга",
      "age": 32,
      "city": "Екатеринбург"
    },
    {
      "name": "Дмитрий",
      "age": 29,
      "city": "Ростов"
    }
  ]
}
*/

Продвинутые техники работы с JSON

Дженерики для универсального парсинга

Используйте дженерики для создания универсальной функции парсинга:

function safeParseJSON<T>(json: string, validator: (data: unknown) => data is T): T | null {
  try {
    const parsed = JSON.parse(json);
    if (validator(parsed)) {
      return parsed;
    }
    return null;
  } catch {
    return null;
  }
}

// Функция-валидатор для типа User
function isUser(data: unknown): data is User {
  return (
    typeof data === 'object' && data !== null &&
    typeof (data as User).name === 'string' &&
    typeof (data as User).age === 'number' &&
    typeof (data as User).city === 'string'
  );
}

const user = safeParseJSON<User>(
  '{"name": "Елена", "age": 27, "city": "Самара"}',
  isUser
);

if (user) {
  console.log(`Привет, ${user.name}!`);
}

Работа с датами и специальными типами

JSON не поддерживает тип Date напрямую. При сериализации даты преобразуются в строки:

interface Event {
  title: string;
  date: Date;
  participants: number;
}

const event: Event = {
  title: 'Конференция',
  date: new Date('2025-06-15'),
  participants: 200
};

const json                

Блоги

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