> Использовали ли кастомные парсеры для преобразования JSON в объекты на уровне бизнес-логики (JavaScript)

Уровень: senior · Роль: frontend · Категория: Технические вопросы

Компании: Dogma

Стек: JavaScript

> Пример ответа

Короткий ответ

Да, кастомные парсеры для JSON на уровне бизнес-логики используются, когда стандартный JSON.parse не подходит: нужна валидация схемы, трансформация типов (например, строки в Date), обработка ошибок с контекстом или поддержка нестандартных форматов (BigInt, undefined). Это повышает надежность, но добавляет сложность. В современных проектах часто заменяют библиотеками вроде Zod, io-ts или class-transformer.

Подробное объяснение

Кастомные парсеры JSON на уровне бизнес-логики применяются в нескольких сценариях:

  • Валидация и типизация: JSON.parse не проверяет структуру данных. Кастомный парсер гарантирует, что объект соответствует ожидаемой схеме (например, обязательные поля, типы значений).
  • Трансформация типов: JSON поддерживает только строки, числа, булевы, null, массивы и объекты. Кастомный парсер преобразует строки в Date, BigInt, Map, Set или другие специфичные для приложения типы.
  • Обработка ошибок: Стандартный JSON.parse выбрасывает общее SyntaxError. Кастомный парсер может добавить контекст (какое поле, какая строка), логирование или fallback-значения.
  • Поддержка расширенных форматов: Например, парсинг JSON с комментариями, trailing commas, или специфичных для проекта соглашений (snake_case → camelCase).
  • Безопасность: При работе с ненадёжными данными кастомный парсер может отфильтровать опасные поля или ограничить глубину вложенности.

Trade-off: кастомный парсер увеличивает код и время выполнения. Для простых случаев достаточно JSON.parse с TypeScript-типами. Для сложных проектов лучше использовать библиотеки (Zod, io-ts, Ajv), которые предоставляют декларативные схемы и генерацию типов.

На практике

В реальных проектах кастомные парсеры чаще всего встречаются:

  • API-слой: при получении данных с сервера, где нужно преобразовать snake_case в camelCase и валидировать ответ.
  • LocalStorage / IndexedDB: при чтении сохранённых данных, которые могут быть устаревшей версии - нужна миграция.
  • WebSocket / SSE: при потоковой передаче, где каждый чанк нужно парсить и валидировать отдельно.
  • Конфигурационные файлы: где значения могут быть в разных форматах (строка "10s" → число 10000).

Типичный подход - создать функцию-парсер для каждой сущности, которая принимает unknown и возвращает типизированный объект или выбрасывает ошибку с контекстом.

Пример кода

TYPESCRIPT
// Кастомный парсер для пользователя
interface User {
id: number;
name: string;
createdAt: Date;
roles: Set<string>;
}
function parseUser(data: unknown): User {
if (typeof data !== 'object' || data === null) {
throw new Error('User must be an object');
}
const obj = data as Record<string, unknown>;
if (typeof obj.id !== 'number' || !Number.isInteger(obj.id)) {
throw new Error(`Invalid user id: ${obj.id}`);
}
if (typeof obj.name !== 'string' || obj.name.length === 0) {
throw new Error(`Invalid user name: ${obj.name}`);
}
let createdAt: Date;
if (typeof obj.createdAt === 'string') {
createdAt = new Date(obj.createdAt);
if (isNaN(createdAt.getTime())) {
throw new Error(`Invalid date: ${obj.createdAt}`);
}
} else {
throw new Error('createdAt must be a string');
}
if (!Array.isArray(obj.roles)) {
throw new Error('roles must be an array');
}
const roles = new Set(obj.roles.map(r => String(r)));
return { id: obj.id, name: obj.name, createdAt, roles };
}
// Использование
try {
const raw = JSON.parse('{"id":1,"name":"Alice","createdAt":"2024-01-15","roles":["admin","user"]}');
const user = parseUser(raw);
console.log(user.createdAt.getFullYear()); // 2024
} catch (e) {
console.error('Parsing failed:', e.message);
}

Как отвечать на собеседовании

Начни с прямого ответа: да, используются, но не всегда. Объясни, когда это оправдано (валидация, трансформация типов, обработка ошибок), а когда избыточно (простые данные). Упомяни trade-off: кастомный код vs библиотеки. Приведи конкретный пример из опыта, где кастомный парсер решил проблему (например, миграция данных из LocalStorage). Покажи понимание безопасности и производительности. Закончи рекомендацией: для сложных схем используй Zod или io-ts, для простых - JSON.parse с TypeScript.

Что проверяет интервьюер

  • Понимание ограничений JSON.parse (только синтаксис, не схема).
  • Умение проектировать надёжные парсеры с валидацией и обработкой ошибок.
  • Знание типов данных JavaScript и их JSON-представления.
  • Опыт работы с реальными кейсами (API, storage, миграции).
  • Умение выбирать между кастомным решением и библиотекой.

Типичные ошибки

  • Использование JSON.parse без проверки структуры, полагаясь только на TypeScript (который не работает в runtime).
  • Слишком сложный парсер для простых данных (overengineering).
  • Игнорирование edge cases: null, undefined, NaN, Infinity, циклические ссылки.
  • Отсутствие обработки ошибок с контекстом (какое поле, какое значение).
  • Преобразование типов без валидации (например, new Date(str) без проверки isNaN).
  • Использование eval или Function для парсинга - это опасно.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью