Skip to content

Commit

Permalink
update(JS): web/javascript/reference/global_objects/json/parse (#769)
Browse files Browse the repository at this point in the history
* update(JS): web/javascript/reference/global_objects/json/parse

* Apply suggestions from code review

Co-authored-by: Mykola Myslovskyi <[email protected]>

* Apply suggestions from code review

Co-authored-by: Mykola Myslovskyi <[email protected]>

Co-authored-by: Mykola Myslovskyi <[email protected]>
  • Loading branch information
undead404 and AdriandeCita authored Sep 25, 2022
1 parent bcf2e4f commit dbda6cc
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ browser-compat: javascript.builtins.JSON.parse

{{JSRef}}

Метод **`JSON.parse()`** (розібрати) розбирає рядок у форматі JSON, конструюючи значення чи об'єкт JavaScript, описаний рядком. Можна передати функцію як необов'язковий параметр **reviver** для виконання трансформацій над результівним об'єктом перед його поверненням.
Метод **`JSON.parse()`** (розібрати) розбирає рядок у форматі JSON, конструюючи значення чи об'єкт JavaScript, описаний рядком. Можна передати функцію як необов'язковий параметр _reviver_ для виконання трансформацій над результівним об'єктом перед його поверненням.

{{EmbedInteractiveExample("pages/js/json-parse.html")}}

Expand All @@ -28,41 +28,56 @@ JSON.parse(text, reviver)
- `text` (текст)
- : Рядок, який буде розібрано як JSON. Опис синтаксису JSON можна знайти в розділі про об'єкт {{jsxref("JSON")}}.
- `reviver` (відроджувач) {{optional_inline}}
- : Якщо є функцією — цей параметр прописує те, як початкове, сконструйоване під час розбору, значення слід трансформувати перед його поверненням.
- : Якщо є функцією — цей параметр прописує те, як початкове, сконструйоване під час розбору, значення слід трансформувати перед його поверненням. Невикличні значення ігноруються. Функція викликається з наступними аргументами:
- `key`
- : Ключ, який відповідає значенню.
- `value`
- : Значення – результат розбору.

### Повернене значення

{{jsxref("Object", "Об'єкт")}}, {{jsxref("Array", "Масив")}}, рядок, число, булеве значення або `null`, згідно зі переданим в `text` рядку JSON.
{{jsxref("Object", "Об'єкт")}}, {{jsxref("Array", "Масив")}}, рядок, число, булеве значення або `null`, згідно з переданим в `text` рядком JSON.

### Винятки

Викидає виняток {{jsxref("SyntaxError")}}, якщо переданий для розбору рядок не є дійсним JSON.
- {{jsxref("SyntaxError")}}
- : Викидається, якщо рядок до розбору не є дійсним JSON.

## Опис

`JSON.parse()` розбирає рядок JSON згідно з [граматикою JSON](/uk/docs/Web/JavaScript/Reference/Global_Objects/JSON#full_json_grammar), а потім обчислює рядок так, ніби він був виразом JavaScript. Єдиний випадок, за якого дрібка тексту JSON представляє значення, котре відрізняється від такого самого виразу JavaScript – обробка ключа `"__proto__"`: дивіться [Синтаксис літерала об'єкта і JSON](/uk/docs/Web/JavaScript/Reference/Operators/Object_initializer#syntaksys-literala-obiekta-i-json).

### Параметр reviver

Якщо заданий `reviver` (відновник), то значення, обчислене при розборі, _перетворюється_ перед поверненням. А саме, обчислене значення і всі його властивості (проходом [в глибину](https://uk.wikipedia.org/wiki/%D0%9F%D0%BE%D1%88%D1%83%D0%BA_%D1%83_%D0%B3%D0%BB%D0%B8%D0%B1%D0%B8%D0%BD%D1%83)), починаючи від властивостей найбільшої вкладеності, й аж до самого кореневого значення – пропускаються крізь `reviver`.

`reviver` при виклику отримує об'єкт, котрий містить властивість, що обробляється, як значення `this`, а також два аргументи: `key` та `value`, котрі представляють ім'я в рядковому вигляді (навіть коли об'єкт є масивом) і значення властивості. Якщо функція `reviver` повертає {{jsxref("undefined")}} (чи не повертає жодного значення – наприклад, коли виконання звалюється з кінця функції), то властивість видаляється з об'єкта. Інакше – властивість перевизначається з поверненим значенням. Якщо `reviver` перетворює лише частину значень, то слід пересвідчитися, що всі неперетворені значення повертаються як було: інакше вони будуть видалені з результівного об'єкта.

Подібно до параметра {{jsxref("JSON.stringify()")}} `replacer`, `reviver` в останню чергу викликається на кореневому об'єкті з порожнім рядком як `key` й кореневим об'єктом як `value`. Для тексту JSON, що впізнається за примітивне значення, `reviver` буде викликаний один раз.

Зверніть увагу, що `reviver` спрацьовує після розбору значення. Тому, наприклад, числа в тексті JSON вже будуть перетворені на числа JavaScript, в процесі чого можуть втратити частину точності. Для передачі великих чисел без втрати точності їх слід серіалізувати як рядки – і відновлювати їх до [BigInt](/uk/docs/Web/JavaScript/Reference/Global_Objects/BigInt) чи якогось іншого відповідного довільно точного формату.

## Приклади

### Застосування JSON.parse()

```js
JSON.parse('{}'); // {}
JSON.parse('true'); // true
JSON.parse("{}"); // {}
JSON.parse("true"); // true
JSON.parse('"foo"'); // "foo"
JSON.parse('[1, 5, "false"]'); // [1, 5, "false"]
JSON.parse('null'); // null
JSON.parse("null"); // null
```

### Застосування параметра `reviver`

Якщо було передано параметр `reviver`, обчислене під час розбору значення додатково _трансформується_ перед поверненням із методу. Зокрема, обчислене значення та всі його властивості (починаючи від найглибше вкладених властивостей, і рухаючись до аж до самого значення), кожна окремо проганяються через `reviver`. Далі він викликається, причому `this` містить об'єкт зі властивістю, яка зараз обробляється, а в аргументах до нього передаються назва властивості (як рядок), і її значення. Якщо функція `reviver` повертає {{jsxref("undefined")}} (або не повертає значення взагалі, наприклад — якщо виконання функції зривається до її завершення) — властивість видаляється з об'єкта. Інакше — властивість перевизначається і в неї встановлюється повернене значення.

Якщо `reviver` перетворює лише певні значення, і пропускає інші — варто пересвідчитися, що він їх повертає як є. Інакше їх буде видалено з результівного об'єкта.

```js
JSON.parse(
'{"p": 5}',
(key, value) =>
typeof value === 'number'
typeof value === "number"
? value * 2 // повертає значення * 2 для чисел
: value, // повертає все інше незмінним
: value // повертає все інше незмінним
);

// { p: 10 }
Expand All @@ -81,11 +96,41 @@ JSON.parse('{"1": 1, "2": 2, "3": {"4": 4, "5": {"6": 6}}}', (key, value) => {
// ""
```

### Використання reviver у парі з replacer у JSON.stringify()

Для коректної роботи зі значенням (щоб воно десеріалізувалось до такого самого вихідного об'єкта), процес серіалізації мусить зберігати інформацію про типи. Наприклад, можна застосувати для цього параметр {{jsxref("JSON.stringify()")}} `replacer`:

```js
// Map в загальному випадку серіалізуються як об'єкти без властивостей.
// Можна застосувати замінювач, аби вказати, які записи повинні бути серіалізовані.
const map = new Map([
[1, "один"],
[2, "два"],
[3, "три"],
]);
const jsonText = JSON.stringify(map, (key, value) =>
value instanceof Map ? Array.from(value.entries()) : value
);
console.log(jsonText);
// [[1,"один"],[2,"два"],[3,"три"]]
const map2 = JSON.parse(jsonText, (key, value) =>
key === "" ? new Map(value) : value
);
console.log(map2);
// Map { 1 => "один", 2 => "два", 3 => "три" }
```

Через те, що JSON не має синтаксичного простору для метаданих з анотаціями типу, для відновлення значень, що не є звичайними об'єктами, слід розглянути наступні варіанти:

- Серіалізувати увесь об'єкт у рядок і додати префікс у вигляді тегу типу.
- "Вгадувати" на основі структури даних (наприклад, масив з масивів двох значень)
- Якщо форма даних – фіксована, то на основі імені властивості (наприклад, всі властивості, що звуться `registry`, містять об'єкти `Map`).

### JSON.parse() не допускає висячих ком

```js example-bad
// обидва викинуть SyntaxError
JSON.parse('[1, 2, 3, 4, ]');
JSON.parse("[1, 2, 3, 4, ]");
JSON.parse('{"foo" : 1, }');
```

Expand Down
1 change: 1 addition & 0 deletions uk_spelling_additions.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
декомпонована
декомпоновану
десеріалізації
десеріалізувалось
докеризованого
емах
емів
Expand Down

0 comments on commit dbda6cc

Please sign in to comment.