Сериализация объектов в JavaScript (Node.js): от JSON до бинарных форматов
Сериализация — это процесс преобразования сложной структуры данных (объекта, массива, Map, Set) в формат, который можно сохранить в файл, передать по сети или отправить в другой процесс. В Node.js сериализация используется повсеместно: от REST API до межпроцессного взаимодействия и кэширования. В этой статье мы разберём основные инструменты и библиотеки для сериализации в среде Node.js, их сильные и слабые стороны.
1. Встроенный JSON: стандарт де-факто
Самый простой и популярный способ — использовать глобальный объект JSON с методами JSON.stringify() и JSON.parse(). Он поддерживается нативно в Node.js без установки дополнительных пакетов.
Пример базовой сериализации:
const user = {
name: 'Алексей',
age: 30,
roles: ['admin', 'editor'],
metadata: null
};
// Сериализация в строку
const jsonString = JSON.stringify(user);
console.log(jsonString);
// {"name":"Алексей","age":30,"roles":["admin","editor"],"metadata":null}
// Десериализация обратно в объект
const parsedUser = JSON.parse(jsonString);
console.log(parsedUser.name); // Алексей
Ограничения JSON:
- Не поддерживает функции — методы объекта будут удалены.
- Не поддерживает циклические ссылки — вызовет ошибку
Converting circular structure to JSON. - Игнорирует undefined, Symbol, BigInt (последний вызовет ошибку).
- Преобразует Date в строку — при десериализации не восстанавливается объект Date.
Кастомная сериализация с replacer:
const data = {
name: 'Тест',
date: new Date(),
secret: 'не сохранять',
nested: { value: 42 }
};
const json = JSON.stringify(data, (key, value) => {
if (key === 'secret') return undefined; // исключаем поле
if (value instanceof Date) return value.toISOString(); // явно форматируем дату
return value;
}, 2); // форматирование с отступами
console.log(json);
2. Сериализация через Buffer: для бинарных данных
Когда нужно передавать бинарные данные (изображения, файлы, protobuf), используется класс Buffer. В Node.js Buffer позволяет преобразовывать строки и объекты в бинарный формат и обратно.
Пример с Buffer и JSON:
const obj = { message: 'Привет, мир!' };
// Сериализуем в JSON, затем в Buffer
const buffer = Buffer.from(JSON.stringify(obj), 'utf-8');
console.log(buffer); // <Buffer 7b 22 6d 65 73 73 61 67 65 22 3a 22 d0 9f ...
// Обратно
const restored = JSON.parse(buffer.toString('utf-8'));
console.log(restored.message); // Привет, мир!
Прямая сериализация чисел в Buffer:
const buf = Buffer.alloc(8);
buf.writeInt32LE(255, 0); // записываем 32-битное целое
buf.writeFloatLE(3.14, 4); // записываем float
console.log(buf); // бинарное представление
// Чтение
console.log(buf.readInt32LE(0)); // 255
console.log(buf.readFloatLE(4)); // 3.140000104904175
3. Библиотека flatted: решение для циклических ссылок
Если ваш объект содержит циклические ссылки (например, дерево DOM или граф), стандартный JSON не справится. Библиотека flatted (автор — Andrea Giammarchi) решает эту проблему.
Установка и пример:
npm install flatted
const { stringify, parse } = require('flatted');
const circularObj = { name: 'Цикл' };
circularObj.self = circularObj; // циклическая ссылка
const json = stringify(circularObj);
console.log(json);
// {"name":"Цикл","self":"$1"}
const restored = parse(json);
console.log(restored.name); // Цикл
console.log(restored.self === restored); // true
4. Protocol Buffers (protobuf) через protobufjs
Для высокопроизводительных систем, где важна скорость и компактность (микросервисы, gRPC), используется Protocol Buffers от Google. В Node.js популярна библиотека protobufjs.
Установка:
npm install protobufjs
Пример с определением схемы:
const protobuf = require('protobufjs');
// Определяем