JavaScript и JSON: Полное руководство для разработчиков
Комплексное руководство по работе с JSON в JavaScript: встроенные методы, парсинг, сериализация, обработка ошибок и продвинутые техники.
Big JSON Team
• Technical WriterExpert in JSON data manipulation, API development, and web technologies. Passionate about creating tools that make developers' lives easier.
# 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!
Похожие статьи
Что такое JSON? Полное руководство для начинающих
Узнайте, что такое JSON, его синтаксис, типы данных и области применения. Полное руководство для начинающих по JavaScript Object Notation.
Python и JSON: Полное руководство по работе с данными
Исчерпывающее руководство по работе с JSON в Python: парсинг, сериализация, обработка ошибок, продвинутые техники и best practices.
JSON API и REST сервисы: Полное руководство
Изучите использование JSON в RESTful API, лучшие практики проектирования, аутентификацию и обработку ошибок.