JavaRush /Курсы /Модуль 4: Node.js, Next.js и Angular /Чтение и запись JSON-файлов:

Чтение и запись JSON-файлов: JSON.parse, JSON.stringify

Модуль 4: Node.js, Next.js и Angular
3 уровень , 7 лекция
Открыта

1. Зачем вообще нужен JSON?

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

Почему именно JSON?

  • Его легко читать человеку.
  • Его легко парсить и генерировать программой.
  • Он почти идеально ложится на объекты JavaScript.

Если вы когда-нибудь работали с API, конфигами или даже package.json — вы уже видели JSON в деле.

Как устроен JSON: кратко и по делу

JSON — это некий “универсальный” способ записать объекты и массивы в виде строки.

Пример объекта в JSON:

{
  "name": "Alice",
  "age": 30,
  "isAdmin": false,
  "skills": ["JavaScript", "Node.js"]
}
  • Все ключи — строки в двойных кавычках.
  • Значения — числа, строки, булевы значения, массивы, объекты, null.
  • Никаких комментариев, никаких функций.

В JavaScript такой объект выглядел бы так:

const user = {
  name: "Alice",
  age: 30,
  isAdmin: false,
  skills: ["JavaScript", "Node.js"]
};

2. Два главных героя: JSON.parse и JSON.stringify

Работа с JSON в Node.js (и в браузере) всегда строится вокруг двух методов:

  • JSON.stringify(obj) — превращает объект в строку JSON.
  • JSON.parse(str) — превращает строку JSON обратно в объект.

Пример: сериализация и десериализация

const user = { name: "Bob", age: 25 };
const jsonString = JSON.stringify(user); // '{"name":"Bob","age":25}'
console.log(jsonString);

const parsed = JSON.parse(jsonString); // { name: 'Bob', age: 25 }
console.log(parsed.name); // 'Bob'

Аналогия:
JSON.stringify — это как упаковка посылки для отправки (объект превращается в строку).
JSON.parse — это распаковка посылки (строка снова становится объектом).

3. Чтение JSON-файлов

Теперь перейдём к практике: как прочитать настоящий JSON-файл на диске.

Пример JSON-файла

Пусть у нас есть файл users.json:

[
  { "id": 1, "name": "Alice" },
  { "id": 2, "name": "Bob" }
]

Чтение файла и парсинг

В Node.js читаем файл как строку, а затем превращаем в объект:

const fs = require('fs');

// 1. Читаем файл (синхронно для простоты)
const jsonStr = fs.readFileSync('users.json', 'utf-8');

// 2. Парсим строку в объект
const users = JSON.parse(jsonStr);

console.log(users[0].name); // Alice

Асинхронная версия

const fs = require('fs');

fs.readFile('users.json', 'utf-8', (err, data) => {
  if (err) {
    console.error('Ошибка чтения файла:', err);
    return;
  }
  try {
    const users = JSON.parse(data);
    console.log(users[1].name); // Bob
  } catch (e) {
    console.error('Некорректный JSON:', e.message);
  }
});

Обратите внимание:

  • Файл читается как строка.
  • Только после этого строка превращается в объект через JSON.parse.
  • Если в файле ошибка (например, забыли кавычку), JSON.parse выбросит исключение — поэтому используем try/catch.

Типичные ошибки при чтении JSON

Файл не найден: будет ошибка чтения, не парсинга.

Файл не валиден как JSON: будет ошибка при парсинге (SyntaxError: Unexpected token ...).

Файл не в кодировке utf-8: получите странные символы или ошибку.

4. Запись JSON-файлов

Теперь научимся сохранять объекты в виде JSON-файлов.

Преобразуем объект в строку

const user = { name: "Charlie", age: 28 };
const jsonStr = JSON.stringify(user); // '{"name":"Charlie","age":28}'

Записываем строку в файл

const fs = require('fs');

fs.writeFileSync('user.json', jsonStr, 'utf-8');

Асинхронная запись

const fs = require('fs');

fs.writeFile('user.json', jsonStr, 'utf-8', (err) => {
  if (err) {
    console.error('Ошибка записи файла:', err);
  } else {
    console.log('Файл успешно сохранён!');
  }
});

Форматирование JSON для человека

По умолчанию JSON.stringify делает строку “в одну строку” — неудобно для чтения.
Можно добавить параметры для красивого форматирования:

const jsonStr = JSON.stringify(user, null, 2); // 2 — отступы
fs.writeFileSync('user.json', jsonStr, 'utf-8');

Теперь файл будет выглядеть так:

{
  "name": "Charlie",
  "age": 28
}

Запись массива объектов

const users = [
  { name: "Alice", age: 22 },
  { name: "Bob", age: 31 }
];
fs.writeFileSync('users.json', JSON.stringify(users, null, 2), 'utf-8');

5. Практика: читаем, добавляем, сохраняем

Давайте попробуем реализовать простую функцию “добавить пользователя в файл”.

Пример кода

const fs = require('fs');

function addUser(newUser) {
  // 1. Читаем существующий файл
  let users = [];
  try {
    const data = fs.readFileSync('users.json', 'utf-8');
    users = JSON.parse(data);
  } catch (e) {
    // Если файла нет или он пустой — начинаем с пустого массива
    if (e.code !== 'ENOENT') {
      console.error('Ошибка чтения/парсинга:', e.message);
      return;
    }
  }

  // 2. Добавляем нового пользователя
  users.push(newUser);

  // 3. Сохраняем обратно
  fs.writeFileSync('users.json', JSON.stringify(users, null, 2), 'utf-8');
  console.log('Пользователь добавлен!');
}

// Тестируем
addUser({ name: "Dave", age: 40 });

Комментарии к коду

  • Если файла нет (ENOENT), начинаем с пустого массива.
  • Если файл есть, но повреждён — выводим ошибку.
  • После добавления нового пользователя сохраняем массив обратно в файл.
  • Отступы (2) делают JSON красивым.

6. Использование с асинхронными методами и Promises

С Node.js 10+ можно использовать fs.promises и работать с async/await:

const fs = require('fs').promises;

async function addUserAsync(newUser) {
  let users = [];
  try {
    const data = await fs.readFile('users.json', 'utf-8');
    users = JSON.parse(data);
  } catch (e) {
    if (e.code !== 'ENOENT') {
      console.error('Ошибка:', e.message);
      return;
    }
  }

  users.push(newUser);

  await fs.writeFile('users.json', JSON.stringify(users, null, 2), 'utf-8');
  console.log('Пользователь добавлен (async)!');
}

addUserAsync({ name: "Eve", age: 35 });

7. Типичные ошибки при работе с JSON-файлами

Ошибка №1: забыли преобразовать объект в строку при записи.
Если попытаться записать объект напрямую (fs.writeFileSync('file.json', obj)), получите ошибку: TypeError: Data must be a string or Buffer. Всегда используйте JSON.stringify.

Ошибка №2: забыли парсить строку при чтении.
После чтения файла вы получаете строку, а не объект. Если попытаться обратиться к свойствам строки (data.name), получите undefined.

Ошибка №3: повреждённый JSON-файл.
Если файл был отредактирован вручную и там пропущена запятая или кавычка — JSON.parse выбросит исключение. Всегда используйте try/catch.

Ошибка №4: попытка читать файл, которого нет.
Если файл не существует, readFileSync выбросит ошибку. Обрабатывайте этот случай отдельно — например, начинайте с пустого массива.

Ошибка №5: гонки при асинхронной записи.
Если несколько процессов одновременно пишут в один и тот же JSON-файл, возможна потеря данных. Для сложных сценариев используйте базы данных или блокировки.

Ошибка №6: забыли указать кодировку при чтении/записи.
Если не указать 'utf-8', получите данные в виде Buffer, а не строки. Всегда пишите 'utf-8'.

Ошибка №7: попытка хранить функции или undefined.
JSON не поддерживает функции, undefined, или специальные объекты. Все значения должны быть числами, строками, булевыми, null, массивами или объектами.

1
Задача
Модуль 4: Node.js, Next.js и Angular, 3 уровень, 7 лекция
Недоступна
Преобразование объекта в строку JSON
Преобразование объекта в строку JSON
1
Задача
Модуль 4: Node.js, Next.js и Angular, 3 уровень, 7 лекция
Недоступна
Чтение и парсинг JSON-файла
Чтение и парсинг JSON-файла
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ