Гид по технологиям

Чтение и запись JSON в Node.js

5 min read Node.js Обновлено 30 Dec 2025
Чтение и запись JSON в Node.js
Чтение и запись JSON в Node.js

Две металлические секции ограждения, соединённые цепью; между ними большой зазор, в котором находится зелёный логотип Node.js.

Зачем читать и записывать JSON в Node.js

JSON (JavaScript Object Notation) — текстовый формат для структурированных данных. Он удобен для хранения конфигураций, обмена данными между сервисами и сериализации объектов. В Node.js работа с файловой системой реализуется через модуль fs. Умение корректно читать и записывать JSON-файлы позволяет сохранять состояние приложений, кэшировать данные, экспортировать/импортировать наборы данных и быстро прототипировать сервисы.

Важно: JSON — это текст. Перед записью объект нужно превратить в строку (JSON.stringify), а при чтении — распарсить (JSON.parse).

Коротко о модуле fs

Модуль fs встроен в Node.js и предоставляет два основных режима работы:

  • Асинхронные методы (не блокируют event loop) — рекомендуются для серверных приложений.
  • Синхронные методы (оканчиваются на Sync) — удобны для одноразовых скриптов и запуска в CLI.

Современный стиль — использовать промисы/async-await через путь node:fs/promises (Node.js v18+). Для более старых версий применяется fs/promises.

Чтение JSON-файлов (асинхронно)

Пример чтения файла с использованием промисов и парсинга JSON:

const fs = require("node:fs/promises");

fs.readFile("./users.json", { encoding: "utf-8", flag: "r" })
  .then((data) => {
    const users = JSON.parse(data);
    console.log(users);
  })
  .catch((error) => {
    console.error('Ошибка при чтении JSON-файла:', error);
  });

Пояснения:

  • encoding: “utf-8” — стандарт для текстовых файлов.
  • JSON.parse выбрасывает исключение при некорректном JSON — всегда оборачивайте в try/catch или используйте безопасный валидатор.

Альтернатива для маленьких статичных файлов: require(‘./users.json’) — синхронно прочитает и автоматически распарсит JSON, но результат попадёт в кэш require, что не подходит для часто изменяющихся файлов.

Запись JSON-файлов (асинхронно)

Запись требует передачи строки или буфера, поэтому нужно вызвать JSON.stringify на объекте:

const fs = require("node:fs/promises");

const fakeUsers = [
  {
    id: 1,
    name: "John Doe",
    username: "johndoe123",
    address: {
      street: "123 Main St",
      city: "Anytown",
    },
  },
  {
    id: 2,
    name: "Jane Smith",
    username: "janesmith456",
    address: {
      street: "456 Elm St",
      city: "Another City",
    },
  }
];

fs.writeFile("./users.json", JSON.stringify(fakeUsers, null, 2), {
  encoding: "utf-8",
  flag: "w",
}).catch((error) => {
  console.error('Ошибка при записи JSON-файла:', error);
});

Советы:

  • JSON.stringify(obj, null, 2) даёт человекочитаемый отступ, полезно для конфигов.
  • Флаг “w” перезаписывает файл; используйте “a” для дозаписи (append) с осторожностью.

Обновление JSON-файлов

fs не имеет отдельного метода «обновить». Общая стратегия — прочитать текущее содержимое, модифицировать структуру в памяти и записать обратно.

Пример функции обновления:

const fs = require("node:fs/promises");

const updateFile = async (filePath, data) => {
  try {
    const fileContents = await fs.readFile(filePath, {
      encoding: "utf-8",
      flag: "r",
    });

    const fileData = JSON.parse(fileContents);

    const updatedFileData = [...fileData, ...data];

    await fs.writeFile(filePath, JSON.stringify(updatedFileData, null, 2), {
      encoding: "utf-8",
      flag: "w",
    });

    return "Файл успешно обновлён";
  } catch (error) {
    console.error('Ошибка при обновлении JSON-файла:', error);
  }
};

Вызов функции:

updateFile("./users.json", [
  {
    id: 4,
    name: "Jane Doe",
    username: "janedoe123",
    address: {
      street: "123 Main St",
      city: "Anytown",
    },
  },
  {
    id: 5,
    name: "John Smith",
    username: "johnsmith456",
    address: {
      street: "456 Elm St",
      city: "Another City",
    },
  }
]).then((message) => {
  console.log(message);
});

Важно: при одновременном доступе нескольких процессов возможны состояния гонки — рассмотрите блокировки, временные файлы и атомарную запись.

Безопасность и валидация

Важно защитить приложение при работе с файлами:

  • Всегда валидируйте JSON (структуру и типы) перед использованием данных.
  • Не выполняйте код, полученный из JSON (не eval и т.д.).
  • Ограничьте права доступа к файлам (chown, chmod, ACL) — файлы конфигурации и данные пользователей должны быть доступны только нужным пользователям/службам.
  • Проверяйте пути файлов: не допускайте path traversal (../) через строгую нормализацию и белые списки.
  • Логи ошибок не должны содержать чувствительные данные.

Примечание по GDPR/конфиденциальности: если в JSON хранятся персональные данные, убедитесь в наличии контроля доступа, шифрования при хранении и соответствующей политики удаления.

Когда подход с fs.readFile/fs.writeFile не подходит

  • Большие файлы: чтение целиком в память может привести к OOM. Для больших объёмов используйте потоковую обработку (streams) или разбиение на чанки.
  • Частые параллельные записи: возможны коллизии и потеря данных — применяйте атомарную замену (запись во временный файл + rename) или внешнее хранилище с поддержкой транзакций.
  • Высокая нагрузка и многопроцессность: рассмотрите центрированные хранилища (БД, Redis, S3) вместо локальных файлов.

Альтернативные подходы

  • Потоковая запись и чтение (fs.createReadStream / fs.createWriteStream) — для больших файлов.
  • NDJSON (newline-delimited JSON) — удобен для потоковой обработки и инкрементальных записей.
  • Базы данных (Postgres, MongoDB) — для сложных запросов, индексации и контроля параллелизма.
  • Объектные хранилища (S3) — для распределённого хранения и резервного копирования.

Паттерны надёжной записи

  • Запись во временный файл, проверка завершения записи, затем переименование (atomic rename) заменяет целевой файл.
  • Используйте fsync при необходимости гарантировать сброс данных на диск.
  • При обновлении — применяйте optimistic locking (версия/etag) или блокировки.

Психологические модели и эвристики при выборе подхода

  • Если данные пригодны для представления в виде одного небольшого файла — используйте простую модель read-modify-write.
  • Если данные растут по объёму или требуют конкурентного доступа — переходите на потоковую обработку или СУБД.
  • Правило «первое — безопасность, второе — производительность»: сначала корректность и целостность данных, затем оптимизация.

Малый справочный блок: важные термины

  • JSON: текстовый формат обмена данными.
  • fs: модуль файловой системы в Node.js.
  • stream: API для обработки данных по частям.
  • Atomic rename: операция переименования файла, используемая как атомарная замена.

Чек-листы

Чек-лист для разработчика:

  • Использую асинхронные методы fs в серверном коде.
  • Валидирую JSON прежде чем использовать.
  • Обрабатываю ошибки чтения/записи.
  • Не завишу от require для часто меняющихся файлов.
  • Для больших файлов применяю потоки.

Чек-лист для DevOps/админа:

  • Разрешения файлов ограничены только необходимым процессам.
  • Настроены резервные копии и ротация логов/файлов.
  • Мониторинг ошибок ввода/вывода и свободного места на диске.

Мини-методология (шаги) для безопасного update

  1. Прочитать файл в память асинхронно.
  2. Валидировать и преобразовать данные.
  3. Подготовить новый контент (сериализация с отступами для читабельности, если нужно).
  4. Записать в временный файл (tmp).
  5. Выполнить атомарный rename tmp -> target.
  6. Логировать успех/ошибки и очищать временные файлы.

Решение: какой метод выбрать (диаграмма)

flowchart TD
  A[Нужно работать с JSON?] --> B{Файл небольшой и статичный?}
  B -- Да --> C[fs.readFile / fs.writeFile 'с JSON.parse/stringify']
  B -- Нет --> D{Требуется потоковая обработка?}
  D -- Да --> E[streams 'createReadStream/createWriteStream' или NDJSON]
  D -- Нет --> F{Параллельный доступ/транзакции?}
  F -- Да --> G[БД/объектное хранилище]
  F -- Нет --> C

Примеры ошибок и как их избегать

  • Ошибка: JSON.parse падает на некорректном JSON. Решение: валидировать вход, использовать try/catch.
  • Ошибка: потеря данных при параллельной записи. Решение: атомарная запись и блокировки.
  • Ошибка: переполнение памяти при чтении больших файлов. Решение: использовать потоки.

Итоги

Работа с JSON в Node.js простая и гибкая, но требует внимания к безопасности, обработке ошибок и выбору подходящего метода для объёма и характера данных. Для большинства задач используйте асинхронные fs-методы; для больших объёмов — потоки или специализированные хранилища.

Важно: всегда валидируйте данные и ограничивайте доступ к файлам.

Краткое резюме:

  • fs.readFile + JSON.parse — для чтения.
  • fs.writeFile + JSON.stringify — для записи.
  • Для обновления — read-modify-write с атомарной заменой.
  • Для больших/конкурентных задач — streams или БД.

1-строчный глоссарий:

  • JSON — формат обмена; fs — модуль для работы с файлами; stream — поток данных.

Ключевые шаги при распространённых сценариях:

  • Конфиг: слушайте small JSON + человекочитаемый stringify.
  • Кэш: require подходит только для неизменяемых, редко обновляемых файлов.
  • Логика обновления: используйте временные файлы и atomic rename.
Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

3D эффект вырывающегося изображения в Photoshop
Фотография

3D эффект вырывающегося изображения в Photoshop

Как оценить приложение в App Store на iPhone
Мобильные приложения

Как оценить приложение в App Store на iPhone

Учимся C: Hello World и основы
Программирование

Учимся C: Hello World и основы

Где смотреть Супербоул LVIII (2024): кабель и стриминг
Спорт

Где смотреть Супербоул LVIII (2024): кабель и стриминг

Как использовать один номер на двух телефонах
Телефония

Как использовать один номер на двух телефонах

Как отправлять деньги создателям на Clubhouse
Монетизация

Как отправлять деньги создателям на Clubhouse