← Вернуться к блогу

JavaScript и JSON: Полное руководство для разработчиков

Комплексное руководство по работе с JSON в JavaScript: встроенные методы, парсинг, сериализация, обработка ошибок и продвинутые техники.

Big JSON Team14 мин чтенияprogramming
B

Big JSON Team

Technical Writer

Expert in JSON data manipulation, API development, and web technologies. Passionate about creating tools that make developers' lives easier.

14 мин чтения

# JavaScript и JSON: Полное руководство для разработчиков

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

JSON в JavaScript: Основы

JSON (JavaScript Object Notation) изначально был создан как подмножество JavaScript, поэтому работа с ним в этом языке максимально естественна.

Глобальный объект JSON

JavaScript предоставляет встроенный объект JSON с двумя основными методами:

  • JSON.parse() — преобразует JSON строку в JavaScript объект
  • JSON.stringify() — преобразует JavaScript объект в JSON строку

Парсинг JSON (JSON.parse)

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

// JSON строка

const jsonString = '{"имя": "Иван", "возраст": 30, "город": "Москва"}';

// Парсинг в JavaScript объект

const объект = JSON.parse(jsonString);

console.log(объект.имя); // "Иван"

console.log(объект.возраст); // 30

console.log(typeof объект); // "object"

Парсинг массивов

const jsonArray = '[{"id": 1, "название": "Продукт 1"}, {"id": 2, "название": "Продукт 2"}]';

const продукты = JSON.parse(jsonArray);

console.log(Array.isArray(продукты)); // true

console.log(продукты.length); // 2

console.log(продукты[0].название); // "Продукт 1"

Парсинг с reviver функцией

const jsonWithDate = '{"название": "Событие", "дата": "2026-01-26T10:00:00Z"}';

// Reviver функция для преобразования дат

const объект = JSON.parse(jsonWithDate, (ключ, значение) => {

if (ключ === 'дата') {

return new Date(значение);

}

return значение;

});

console.log(объект.дата instanceof Date); // true

console.log(объект.дата.getFullYear()); // 2026

Обработка ошибок парсинга

function безопасныйПарсинг(jsonString) {

try {

return {

success: true,

data: JSON.parse(jsonString),

error: null

};

} catch (error) {

return {

success: false,

data: null,

error: error.message

};

}

}

// Использование

const результат1 = безопасныйПарсинг('{"имя": "Иван"}');

console.log(результат1.success); // true

const результат2 = безопасныйПарсинг('{"имя": Иван}'); // Невалидный JSON

console.log(результат2.success); // false

console.log(результат2.error); // Сообщение об ошибке

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

Базовая сериализация

const пользователь = {

имя: "Мария Иванова",

возраст: 28,

email: "maria@example.com",

активна: true,

баланс: null

};

const jsonString = JSON.stringify(пользователь);

console.log(jsonString);

// {"имя":"Мария Иванова","возраст":28,"email":"maria@example.com","активна":true,"баланс":null}

Форматирование с отступами

const пользователь = {

имя: "Петр",

навыки: ["JavaScript", "Python", "Go"]

};

// С отступом 2 пробела

const formatted = JSON.stringify(пользователь, null, 2);

console.log(formatted);

Результат:
{

"имя": "Петр",

"навыки": [

"JavaScript",

"Python",

"Go"

]

}

Replacer функция

Фильтрация свойств:
const пользователь = {

имя: "Иван",

пароль: "secret123",

email: "ivan@example.com",

возраст: 30

};

// Исключить пароль

const безПароля = JSON.stringify(пользователь, (ключ, значение) => {

if (ключ === 'пароль') {

return undefined; // Исключить это свойство

}

return значение;

}, 2);

console.log(безПароля);

Replacer как массив:
const данные = {

id: 1,

имя: "Иван",

пароль: "secret",

email: "ivan@example.com"

};

// Включить только id и имя

const filtered = JSON.stringify(данные, ['id', 'имя'], 2);

console.log(filtered);

// {

// "id": 1,

// "имя": "Иван"

// }

Метод toJSON()

class Пользователь {

constructor(имя, возраст, пароль) {

this.имя = имя;

this.возраст = возраст;

this.пароль = пароль;

}

// Кастомная сериализация

toJSON() {

return {

имя: this.имя,

возраст: this.возраст

// пароль намеренно исключен

};

}

}

const пользователь = new Пользователь("Анна", 25, "secret123");

const json = JSON.stringify(пользователь, null, 2);

console.log(json);

// {

// "имя": "Анна",

// "возраст": 25

// }

Типы данных JavaScript ↔ JSON

Поддерживаемые типы

const данные = {

строка: "текст",

число: 42,

дробное: 3.14,

булево: true,

null: null,

массив: [1, 2, 3],

объект: { ключ: "значение" }

};

const json = JSON.stringify(данные);

console.log(json);

Неподдерживаемые типы

const данные = {

функция: function() { return "привет"; }, // Будет undefined

символ: Symbol("test"), // Будет undefined

undefined: undefined, // Будет исключено

дата: new Date(), // Станет строкой

регвыр: /test/, // Станет объектом {}

NaN: NaN, // Станет null

Infinity: Infinity // Станет null

};

console.log(JSON.stringify(данные, null, 2));

Результат:
{

"дата": "2026-01-26T10:00:00.000Z",

"регвыр": {},

"NaN": null,

"Infinity": null

}

Обработка Date объектов

const событие = {

название: "Встреча",

дата: new Date('2026-01-26T10:00:00Z')

};

// Сериализация

const json = JSON.stringify(событие);

console.log(json);

// {"название":"Встреча","дата":"2026-01-26T10:00:00.000Z"}

// Парсинг обратно

const parsed = JSON.parse(json, (ключ, значение) => {

if (ключ === 'дата') {

return new Date(значение);

}

return значение;

});

console.log(parsed.дата instanceof Date); // true

Работа с API

Fetch API

GET запрос:
async function получитьПользователей() {

try {

const response = await fetch('https://api.example.com/users');

if (!response.ok) {

throw new Error(HTTP error! status: ${response.status});

}

// Автоматический парсинг JSON

const пользователи = await response.json();

return пользователи;

} catch (error) {

console.error('Ошибка загрузки:', error);

throw error;

}

}

// Использование

получитьПользователей()

.then(пользователи => {

пользователи.forEach(п => console.log(п.имя));

});

POST запрос:
async function создатьПользователя(имя, email) {

const данные = {

имя: имя,

email: email,

активен: true

};

try {

const response = await fetch('https://api.example.com/users', {

method: 'POST',

headers: {

'Content-Type': 'application/json',

},

body: JSON.stringify(данные) // Сериализация в JSON

});

if (!response.ok) {

throw new Error(HTTP error! status: ${response.status});

}

const результат = await response.json();

return результат;

} catch (error) {

console.error('Ошибка создания:', error);

throw error;

}

}

// Использование

создатьПользователя("Анна", "anna@example.com")

.then(пользователь => console.log(Создан ID: ${пользователь.id}));

XMLHttpRequest (legacy)

function отправитьЗапрос(url, данные, callback) {

const xhr = new XMLHttpRequest();

xhr.open('POST', url, true);

xhr.setRequestHeader('Content-Type', 'application/json');

xhr.onload = function() {

if (xhr.status === 200) {

const ответ = JSON.parse(xhr.responseText);

callback(null, ответ);

} else {

callback(new Error(Ошибка: ${xhr.status}), null);

}

};

xhr.onerror = function() {

callback(new Error('Ошибка сети'), null);

};

xhr.send(JSON.stringify(данные));

}

LocalStorage и JSON

Сохранение объектов

// Сохранение

const настройки = {

тема: "темная",

язык: "ru",

уведомления: true

};

localStorage.setItem('настройки', JSON.stringify(настройки));

// Загрузка

const загруженные = JSON.parse(localStorage.getItem('настройки'));

console.log(загруженные.тема); // "темная"

Утилиты для работы с localStorage

class JSONStorage {

static set(ключ, значение) {

try {

localStorage.setItem(ключ, JSON.stringify(значение));

return true;

} catch (error) {

console.error('Ошибка сохранения:', error);

return false;

}

}

static get(ключ, поУмолчанию = null) {

try {

const значение = localStorage.getItem(ключ);

return значение ? JSON.parse(значение) : поУмолчанию;

} catch (error) {

console.error('Ошибка загрузки:', error);

return поУмолчанию;

}

}

static remove(ключ) {

localStorage.removeItem(ключ);

}

static clear() {

localStorage.clear();

}

}

// Использование

JSONStorage.set('пользователь', { имя: "Иван", id: 123 });

const пользователь = JSONStorage.get('пользователь');

console.log(пользователь.имя); // "Иван"

Deep Clone с JSON

Простое клонирование

const оригинал = {

имя: "Иван",

адрес: {

город: "Москва",

улица: "Тверская"

},

навыки: ["JS", "Python"]

};

// Deep clone через JSON

const клон = JSON.parse(JSON.stringify(оригинал));

// Изменение клона не влияет на оригинал

клон.адрес.город = "Санкт-Петербург";

клон.навыки.push("Go");

console.log(оригинал.адрес.город); // "Москва" (не изменилось)

console.log(клон.адрес.город); // "Санкт-Петербург"

Ограничения метода

const данные = {

дата: new Date(),

функция: () => "привет",

undefined: undefined,

символ: Symbol("test"),

цикл: null

};

данные.цикл = данные; // Циклическая ссылка

// Это НЕ сработает для:

// - функций (будут потеряны)

// - Date (станет строкой)

// - undefined (будет исключено)

// - Symbol (будет исключен)

// - циклических ссылок (ошибка)

try {

const клон = JSON.parse(JSON.stringify(данные));

} catch (error) {

console.error('Ошибка:', error.message);

// TypeError: Converting circular structure to JSON

}

Сравнение JSON объектов

function сравнитьJSON(obj1, obj2) {

return JSON.stringify(obj1) === JSON.stringify(obj2);

}

const объект1 = { имя: "Иван", возраст: 30 };

const объект2 = { имя: "Иван", возраст: 30 };

const объект3 = { возраст: 30, имя: "Иван" }; // Другой порядок

console.log(сравнитьJSON(объект1, объект2)); // true

console.log(сравнитьJSON(объект1, объект3)); // false (разный порядок ключей!)

Улучшенное сравнение:
function глубокоеСравнение(obj1, obj2) {

// Сортировка ключей перед сравнением

const нормализовать = (obj) => {

if (Array.isArray(obj)) {

return obj.map(нормализовать);

} else if (typeof obj === 'object' && obj !== null) {

return Object.keys(obj)

.sort()

.reduce((результат, ключ) => {

результат[ключ] = нормализовать(obj[ключ]);

return результат;

}, {});

}

return obj;

};

return JSON.stringify(нормализовать(obj1)) ===

JSON.stringify(нормализовать(obj2));

}

console.log(глубокоеСравнение(объект1, объект3)); // true

Продвинутые техники

Streaming JSON

// Для больших JSON данных используйте streaming

async function обработатьБольшойJSON(url) {

const response = await fetch(url);

const reader = response.body.getReader();

const decoder = new TextDecoder();

let buffer = '';

while (true) {

const { done, value } = await reader.read();

if (done) break;

buffer += decoder.decode(value, { stream: true });

// Обработка частями (если JSON это массив)

const части = buffer.split('\n');

buffer = части.pop(); // Сохранить неполную часть

for (const часть of части) {

if (часть.trim()) {

const объект = JSON.parse(часть);

обработатьОбъект(объект);

}

}

}

}

function обработатьОбъект(obj) {

console.log('Обработка:', obj);

}

JSON Schema валидация

function валидироватьПользователя(пользователь) {

const схема = {

имя: { type: 'string', required: true, minLength: 1 },

возраст: { type: 'number', required: true, min: 0, max: 150 },

email: { type: 'string', required: true, pattern: /@/ }

};

const ошибки = [];

for (const [ключ, правила] of Object.entries(схема)) {

const значение = пользователь[ключ];

if (правила.required && значение === undefined) {

ошибки.push(Поле ${ключ} обязательно);

continue;

}

if (правила.type && typeof значение !== правила.type) {

ошибки.push(Поле ${ключ} должно быть типа ${правила.type});

}

if (правила.minLength && значение.length < правила.minLength) {

ошибки.push(Поле ${ключ} слишком короткое);

}

if (правила.pattern && !правила.pattern.test(значение)) {

ошибки.push(Поле ${ключ} не соответствует формату);

}

}

return {

valid: ошибки.length === 0,

errors: ошибки

};

}

// Тестирование

const результат = валидироватьПользователя({

имя: "Иван",

возраст: 30,

email: "invalid-email"

});

console.log(результат);

Pretty Print в консоли

function красивыйВывод(объект, метка = '') {

if (метка) console.log(метка);

console.log(JSON.stringify(объект, null, 2));

}

// С цветами (в Node.js)

function цветнойВывод(объект) {

console.dir(объект, {

colors: true,

depth: null

});

}

// Использование

красивыйВывод({ имя: "Иван", навыки: ["JS", "Python"] }, 'Пользователь:');

Best Practices

1. Всегда обрабатывайте ошибки

// Плохо

const данные = JSON.parse(неизвестнаяСтрока);

// Хорошо

try {

const данные = JSON.parse(неизвестнаяСтрока);

// работа с данными

} catch (error) {

console.error('Ошибка парсинга JSON:', error);

// обработка ошибки

}

2. Валидируйте данные из API

async function получитьДанные(url) {

const response = await fetch(url);

const данные = await response.json();

// Валидация

if (!Array.isArray(данные)) {

throw new Error('Ожидался массив');

}

if (!данные.every(item => item.id && item.name)) {

throw new Error('Невалидная структура данных');

}

return данные;

}

3. Не используйте eval()

// ОПАСНО! Никогда не делайте так:

const данные = eval('(' + jsonString + ')');

// БЕЗОПАСНО:

const данные = JSON.parse(jsonString);

4. Ограничивайте глубину вложенности

function ограничитьГлубину(obj, maxDepth = 10, currentDepth = 0) {

if (currentDepth >= maxDepth) {

return '[Слишком глубоко]';

}

if (typeof obj !== 'object' || obj === null) {

return obj;

}

if (Array.isArray(obj)) {

return obj.map(item => ограничитьГлубину(item, maxDepth, currentDepth + 1));

}

const результат = {};

for (const [ключ, значение] of Object.entries(obj)) {

результат[ключ] = ограничитьГлубину(значение, maxDepth, currentDepth + 1);

}

return результат;

}

5. Используйте TypeScript для типобезопасности

interface Пользователь {

имя: string;

возраст: number;

email: string;

}

function парситьПользователя(jsonString: string): Пользователь {

const данные = JSON.parse(jsonString);

// Валидация типов во время выполнения

if (typeof данные.имя !== 'string' ||

typeof данные.возраст !== 'number' ||

typeof данные.email !== 'string') {

throw new Error('Невалидные данные пользователя');

}

return данные as Пользователь;

}

Заключение

JavaScript предоставляет мощные встроенные инструменты для работы с JSON. Понимание тонкостей JSON.parse() и JSON.stringify() позволяет эффективно работать с данными в веб-приложениях.

Ключевые моменты:
  • Используйте JSON.parse() и JSON.stringify() для конвертации
  • Всегда обрабатывайте ошибки парсинга
  • Помните об ограничениях при сериализации (функции, даты, циклические ссылки)
  • Используйте replacer/reviver функции для кастомной обработки
  • Валидируйте данные из внешних источников
  • Не используйте eval() для парсинга JSON

С этим руководством вы готовы профессионально работать с JSON в JavaScript!

Share:

Похожие статьи

Read in English