Когда вы открываете ленту Instagram, браузер делает запрос к серверу. Сервер написан на Python или Go — совсем другой язык, другие типы данных. Как передать объект? Его нужно сериализовать в текст — и JSON стал универсальным языком для этого. Сегодня JSON используется в 99% веб-API.
JSON (JavaScript Object Notation) — текстовый формат данных. Выглядит как JS-объект, но со строгими правилами:
[1, 2, 3]const user = {
name: 'Алексей',
age: 28,
isAdmin: false,
tags: ['js', 'react'],
}
JSON.stringify(user)
// '{"name":"Алексей","age":28,"isAdmin":false,"tags":["js","react"]}'
// С форматированием (для читаемости / логов):
JSON.stringify(user, null, 2)
// {
// "name": "Алексей",
// "age": 28,
// ...
// }const str = '{"name":"Алексей","age":28}'
const obj = JSON.parse(str)
console.log(obj.name) // 'Алексей'
console.log(typeof obj.age) // 'number' — тип восстановленconst data = {
name: 'Тест',
fn: function() {}, // функция — ИГНОРИРУЕТСЯ
symbol: Symbol(), // Symbol — ИГНОРИРУЕТСЯ
undef: undefined, // undefined — ИГНОРИРУЕТСЯ
date: new Date(), // Date → строка '2024-01-15T10:30:00.000Z'
map: new Map(), // Map → {}
regexp: /abc/, // RegExp → {}
}
console.log(JSON.stringify(data))
// {"name":"Тест","date":"2024-01-15T10:30:00.000Z","map":{},"regexp":{}}// replacer — управляет что включать в JSON
const sensitive = { name: 'Иван', password: 'secret', age: 25 }
const safe = JSON.stringify(sensitive, ['name', 'age']) // только эти поля
// '{"name":"Иван","age":25}'
// reviver — восстанавливает типы при парсинге
const withDate = '{"name":"Иван","createdAt":"2024-01-15T10:00:00.000Z"}'
const parsed = JSON.parse(withDate, (key, value) => {
if (key === 'createdAt') return new Date(value) // строку → Date
return value
})
console.log(parsed.createdAt instanceof Date) // true// Простой способ — работает для простых данных без функций и Date
const original = { user: { name: 'Алексей', scores: [10, 20, 30] } }
const copy = JSON.parse(JSON.stringify(original))
copy.user.name = 'Иван'
console.log(original.user.name) // 'Алексей' — не изменился
// Лучший способ (ES2022):
const copy = structuredClone(original) // сохраняет Date, Map, SetОшибка 1: JSON.parse без try/catch
// Сломано — если строка невалидна, выбросит SyntaxError:
const data = JSON.parse(localStorage.getItem('data')) // может упасть!
// Исправлено:
function safeParse(str, fallback = null) {
try {
return JSON.parse(str)
} catch {
return fallback
}
}Ошибка 2: циклические ссылки
// Сломано:
const obj = { name: 'test' }
obj.self = obj // obj ссылается на себя
JSON.stringify(obj) // TypeError: Converting circular structure to JSON
// Исправлено — structuredClone тоже не поможет, нужна обработка:
// Используй библиотеку или вручную удали циклическую ссылкуОшибка 3: путаница с Date
// Date → строка при stringify, обратно не восстанавливается автоматически:
const obj = { date: new Date() }
const str = JSON.stringify(obj)
const back = JSON.parse(str)
console.log(back.date instanceof Date) // false — это строка!
console.log(typeof back.date) // 'string'
// Исправлено — используй reviver или конвертируй явно:
new Date(back.date)Content-Type: application/json)console.log(JSON.stringify(data, null, 2)) для читаемых логовРабота с API: сериализация, десериализация, безопасный парсинг
// Симуляция работы с API ответом
const rawApiResponse = `{
"status": "ok",
"data": {
"products": [
{"id": 1, "name": "Ноутбук", "price": 75000, "inStock": true},
{"id": 2, "name": "Мышь", "price": 1500, "inStock": false},
{"id": 3, "name": "Коврик", "price": 500, "inStock": true}
],
"total": 3,
"updatedAt": "2024-01-15T10:30:00.000Z"
}
}`
// Парсинг с восстановлением дат
function parseApiResponse(jsonStr) {
try {
return JSON.parse(jsonStr, (key, value) => {
if (typeof value === 'string' && /^\d{4}-\d{2}-\d{2}T/.test(value)) {
return new Date(value)
}
return value
})
} catch (e) {
console.error('Ошибка парсинга:', e.message)
return null
}
}
const response = parseApiResponse(rawApiResponse)
console.log(response.status) // 'ok'
console.log(response.data.total) // 3
console.log(response.data.updatedAt instanceof Date) // true
// Фильтрация и сериализация для сохранения
const inStock = response.data.products.filter(p => p.inStock)
const forSave = JSON.stringify({ products: inStock }, null, 2)
console.log(forSave)
// {
// "products": [
// { "id": 1, "name": "Ноутбук", "price": 75000, "inStock": true },
// { "id": 3, "name": "Коврик", "price": 500, "inStock": true }
// ]
// }
// Безопасное хранение в "localStorage" (симуляция)
const storage = {}
function saveToStorage(key, data) {
storage[key] = JSON.stringify(data)
}
function loadFromStorage(key, fallback = null) {
try {
const raw = storage[key]
return raw != null ? JSON.parse(raw) : fallback
} catch {
return fallback
}
}
saveToStorage('cart', inStock)
const loaded = loadFromStorage('cart', [])
console.log(loaded.length) // 2
console.log(loaded[0].name) // 'Ноутбук'
console.log(loadFromStorage('x', []).length) // 0 — fallbackКогда вы открываете ленту Instagram, браузер делает запрос к серверу. Сервер написан на Python или Go — совсем другой язык, другие типы данных. Как передать объект? Его нужно сериализовать в текст — и JSON стал универсальным языком для этого. Сегодня JSON используется в 99% веб-API.
JSON (JavaScript Object Notation) — текстовый формат данных. Выглядит как JS-объект, но со строгими правилами:
[1, 2, 3]const user = {
name: 'Алексей',
age: 28,
isAdmin: false,
tags: ['js', 'react'],
}
JSON.stringify(user)
// '{"name":"Алексей","age":28,"isAdmin":false,"tags":["js","react"]}'
// С форматированием (для читаемости / логов):
JSON.stringify(user, null, 2)
// {
// "name": "Алексей",
// "age": 28,
// ...
// }const str = '{"name":"Алексей","age":28}'
const obj = JSON.parse(str)
console.log(obj.name) // 'Алексей'
console.log(typeof obj.age) // 'number' — тип восстановленconst data = {
name: 'Тест',
fn: function() {}, // функция — ИГНОРИРУЕТСЯ
symbol: Symbol(), // Symbol — ИГНОРИРУЕТСЯ
undef: undefined, // undefined — ИГНОРИРУЕТСЯ
date: new Date(), // Date → строка '2024-01-15T10:30:00.000Z'
map: new Map(), // Map → {}
regexp: /abc/, // RegExp → {}
}
console.log(JSON.stringify(data))
// {"name":"Тест","date":"2024-01-15T10:30:00.000Z","map":{},"regexp":{}}// replacer — управляет что включать в JSON
const sensitive = { name: 'Иван', password: 'secret', age: 25 }
const safe = JSON.stringify(sensitive, ['name', 'age']) // только эти поля
// '{"name":"Иван","age":25}'
// reviver — восстанавливает типы при парсинге
const withDate = '{"name":"Иван","createdAt":"2024-01-15T10:00:00.000Z"}'
const parsed = JSON.parse(withDate, (key, value) => {
if (key === 'createdAt') return new Date(value) // строку → Date
return value
})
console.log(parsed.createdAt instanceof Date) // true// Простой способ — работает для простых данных без функций и Date
const original = { user: { name: 'Алексей', scores: [10, 20, 30] } }
const copy = JSON.parse(JSON.stringify(original))
copy.user.name = 'Иван'
console.log(original.user.name) // 'Алексей' — не изменился
// Лучший способ (ES2022):
const copy = structuredClone(original) // сохраняет Date, Map, SetОшибка 1: JSON.parse без try/catch
// Сломано — если строка невалидна, выбросит SyntaxError:
const data = JSON.parse(localStorage.getItem('data')) // может упасть!
// Исправлено:
function safeParse(str, fallback = null) {
try {
return JSON.parse(str)
} catch {
return fallback
}
}Ошибка 2: циклические ссылки
// Сломано:
const obj = { name: 'test' }
obj.self = obj // obj ссылается на себя
JSON.stringify(obj) // TypeError: Converting circular structure to JSON
// Исправлено — structuredClone тоже не поможет, нужна обработка:
// Используй библиотеку или вручную удали циклическую ссылкуОшибка 3: путаница с Date
// Date → строка при stringify, обратно не восстанавливается автоматически:
const obj = { date: new Date() }
const str = JSON.stringify(obj)
const back = JSON.parse(str)
console.log(back.date instanceof Date) // false — это строка!
console.log(typeof back.date) // 'string'
// Исправлено — используй reviver или конвертируй явно:
new Date(back.date)Content-Type: application/json)console.log(JSON.stringify(data, null, 2)) для читаемых логовРабота с API: сериализация, десериализация, безопасный парсинг
// Симуляция работы с API ответом
const rawApiResponse = `{
"status": "ok",
"data": {
"products": [
{"id": 1, "name": "Ноутбук", "price": 75000, "inStock": true},
{"id": 2, "name": "Мышь", "price": 1500, "inStock": false},
{"id": 3, "name": "Коврик", "price": 500, "inStock": true}
],
"total": 3,
"updatedAt": "2024-01-15T10:30:00.000Z"
}
}`
// Парсинг с восстановлением дат
function parseApiResponse(jsonStr) {
try {
return JSON.parse(jsonStr, (key, value) => {
if (typeof value === 'string' && /^\d{4}-\d{2}-\d{2}T/.test(value)) {
return new Date(value)
}
return value
})
} catch (e) {
console.error('Ошибка парсинга:', e.message)
return null
}
}
const response = parseApiResponse(rawApiResponse)
console.log(response.status) // 'ok'
console.log(response.data.total) // 3
console.log(response.data.updatedAt instanceof Date) // true
// Фильтрация и сериализация для сохранения
const inStock = response.data.products.filter(p => p.inStock)
const forSave = JSON.stringify({ products: inStock }, null, 2)
console.log(forSave)
// {
// "products": [
// { "id": 1, "name": "Ноутбук", "price": 75000, "inStock": true },
// { "id": 3, "name": "Коврик", "price": 500, "inStock": true }
// ]
// }
// Безопасное хранение в "localStorage" (симуляция)
const storage = {}
function saveToStorage(key, data) {
storage[key] = JSON.stringify(data)
}
function loadFromStorage(key, fallback = null) {
try {
const raw = storage[key]
return raw != null ? JSON.parse(raw) : fallback
} catch {
return fallback
}
}
saveToStorage('cart', inStock)
const loaded = loadFromStorage('cart', [])
console.log(loaded.length) // 2
console.log(loaded[0].name) // 'Ноутбук'
console.log(loadFromStorage('x', []).length) // 0 — fallbackСоздай мини-систему сохранения настроек приложения. Напиши функцию createSettingsStore(defaultSettings), которая возвращает объект с методами: save(settings) — сохраняет настройки в storage (симулируй через объект), load() — загружает и парсит, возвращая defaultSettings при ошибке, update(partial) — загружает текущие настройки, сливает с partial и сохраняет, reset() — удаляет сохранённые настройки.
save: storage[KEY] = JSON.stringify(settings). load: JSON.parse(raw). update: save({ ...current, ...partial }). Ключ spread сначала current, потом partial — чтобы partial перезаписал.