Формат JSON
JSON (JavaScript Object Notation) - сучасний текстовий формат зберігання і передачі структурованих даних у текстовій формі. Звичний об'єктоподібний синтаксис JSON - дуже зручний. Саме у цьому форматі дані будуть приходити і відправлятися на сервер, зберігатися в локальному сховищі тощо.
Але JSON - це не об'єкт, а його рядкове відображення. Нижче наведено приклад JSON файлу. Синтаксис схожий на об'єкт, за винятком того, що ключі - це завжди рядки у подвійних лапках. Рядкові значення також обов'язково повинні бути взяті у подвійні лапки. Значеннями властивостей можуть бути типи: string
, number
, object
, array
, boolean
і null
.
{
"name": "Josh",
"weight": 175,
"age": 30,
"eyecolor": "brown",
"isHappy": true,
"cars": ["Chevy", "Honda"],
"favoriteBook": {
"title": "The Last Kingdom",
"author": "Bernard Cornwell",
"rating": 8.38
}
}
Javascript і JSON чудово працюють разом, завдяки методам вбудованого класу JSON
, які перетворюють JavaScript об'єкт у JSON і навпаки. Незалежно від того, що у вас є, можна легко отримати зворотне.
Метод JSON.stringify()
Приймає значення і перетворює його у JSON. Значенням може бути число, буль, null, масив або об'єкт. Рядки - це вже валідний JSON, тому в їх перетворенні немає сенсу.
const dog = {
name: "Mango",
age: 3,
isHappy: true,
};
const dogJSON = JSON.stringify(dog);
console.log(dogJSON); // "{"name":"Mango","age":3,"isHappy":true}"
Результат виклику JSON.stringify(dog)
- це валідний JSON (рядок), який може бути збережений у файл або переданий мережею.
Не будь-який JavaScript об'єкт може бути перетворений один до одного у JSON. Наприклад, якщо в об'єкта є методи, то при перетворенні вони будуть проігноровані.
const dog = {
name: "Mango",
age: 3,
isHappy: true,
bark() {
console.log("Woof!");
},
};
const dogJSON = JSON.stringify(dog);
console.log(dogJSON); // "{"name":"Mango","age":3,"isHappy":true}"
Також, при спробі перетворити функцію в JSON, результатом буде undefined
.
JSON.stringify(() => console.log("Well, this is awkward")); // undefined
Метод JSON.parse()
Щоб отримати з JSON валідне JavaScript значення, його необхідно розпарсити (parse
). Це операція зворотна перетворенню в рядок (stringify
). Тепер, коли dog
- це валідний об'єкт, з ним можна працювати звичайним чином.
const json = '{"name":"Mango","age":3,"isHappy":true}';
const dog = JSON.parse(json);
console.log(dog); // {name: "Mango", age: 3, isHappy: true}
console.log(dog.name); // "Mango"
Обробка помилок
Якщо методам класу JSON
передати невалідний JSON, то вони «викинуть» помилку і весь скрипт впаде. Для уникнення цього, використовується конструкція try...catch
, яка дозволяє «ловити» і обробляти помилки виконання скрипта.
try {
// Code that may throw a runtime error
} catch (error) {
// Error handling
}
- Спочатку виконується код всередині блоку
try
. - Якщо помилки відсутні, блок
catch
ігнорується і управління передається далі. - Якщо в блоці
try
сталася помилка, його виконання зупиняється та інтерпретатор переходить до блокуcatch
.
Змінна error
- це об'єкт помилки з інформацією про те, що сталося. У цього об'єкта є кілька корисних властивостей:
name
- тип помилки. Для помилки парса - цеSyntaxError
.message
- повідомлення про деталі помилки.stack
- стек викликів функцій на момент помилки. Використовується для налагодження.
Наприклад, парс рядка призведе до такого сценарію, тому що рядок з символами - це невалідний JSON, оскільки не може бути перетворений у валідне JavaScript значення.
// Script will crash during parse
const data = JSON.parse("Well, this is awkward");
console.log("❌ You won't see this log");
Використовуючи конструкцію try...catch
, ми можемо обробити цей виняток таким чином, щоб скрипт продовжив працювати, навіть у разі помилки.
try {
const data = JSON.parse("Well, this is awkward");
} catch (error) {
console.log(error.name); // "SyntaxError"
console.log(error.message); // Unexpected token W in JSON at position 0
}
console.log("✅ This is fine, we handled parse error in try...catch");
Те саме буде при спробі парса невалідного JSON, який, наприклад, може прийти з бекенду або бути прочитаний з файлу. У прикладі у властивості username
бракує подвійних лапок.
try {
const data = JSON.parse('{username: "Mango"}');
} catch (error) {
console.log(error.name); // "SyntaxError"
console.log(error.message); // "Unexpected token u in JSON at position 1"
}
console.log("✅ This is fine, we handled parse error in try...catch");
Фази виконання коду
В JavaScript код виконується не відразу, для початку рушію потрібно прочитати код і дізнатися, чи можливо його взагалі виконати.
Фаза інтерпретації або оцінки (compile time, evaluation time) - підготовка перед виконанням коду, рушій знаходить синтаксичні помилки, помилки типізації тощо. Тобто код ще не виконується, тільки оцінюється. Якщо ця фаза пройшла успішно, це як мінімум означає, що в коді відсутні синтаксичні помилки і його можна запустити для виконання.
Фаза виконання (runtime) - скрипт починає виконуватися, виконуються інструкції викликів функцій і оцінки виразів, відбувається пошук необхідних ідентифікаторів у відповідних областях видимості тощо.
Якщо ця фаза завершилася успішно, отже скрипт написаний без явних помилок і завершив свою роботу. На цій фазі можуть бути помилки, пов'язані з відсутніми властивостями і змінними, перетворенням типів тощо, тобто щось, що відбувається тільки під час виконання коду.
Спробуйте виконати наступний код. Оскільки ми зробили помилку і замість const
намагаємося оголосити змінну value
ключовим словом cos
, на фазі компіляції буде виявлена синтаксична помилка і фаза виконання навіть не запуститься. В консолі ми відразу побачимо повідомлення про помилку.
console.log('This message will not appear in the console');
cos value = 5;
try...catch
ловить тільки помилки, які виникли під час виконання коду (runtime errors). Це означає, що код повинен бути синтаксично правильним, інакше фаза виконання просто не запуститься. Помилки, які виникають під час фази оцінки, називаються помилками парсингу.