> For the complete documentation index, see [llms.txt](https://strctr.gitbook.io/programming/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://strctr.gitbook.io/programming/01-languages/javascript/01-language/b-structured/b4-json/03-parsing-json.md).

# 03. Parsing JSON

Основные методы для работы с JSON в JavaScript – это:

* `JSON.parse(JSONString)` – читает объекты из строки в формате JSON.
* `JSON.stringify(JSObject)` – превращает объекты в строку в формате JSON. Используется, когда нужно из JavaScript передать данные по сети.

Обе функции, `JSON.stringify()` и `JSON.parse()`, принимают необязательный второй аргумент - функцию, который можно использовать для настройки процесса сериализации и/или восстановления, например, посредством определения списка свойств, подлежащих сериализации, или функции преобразования значений во время сериализации.

## `JSON.stringify()`

Функция `JSON.stringify()` сериализует только перечислимые собственные свойства объекта. Если значение свойства не может быть сериализовано, это свойство просто исключается из строкового представления.

Функция `JSON.stringify(value, replacer?, space?)` преобразует JS-значение в строку в JSON-формате.

* Опциональный параметр `replacer?` используется для замены значения пред преобразованием его в строку.
  * Функция `function(key, value)`, которая может быть использована для замены значений обрабатываемого объекта в процессе его преобразования в JSON.
  * Массив строк, соответствующий ключам, которые должны быть в результирующем JSON.
* Опциональный параметр `space?` позволяет задать форматирование. Без этой этого параметра результатом выполнения будет JSON в одну строку.
  * *Число* будет означать величину отступа.
  * *Строка* паттерн-приставка к каждой строке JSON-а.

Особенности работы `JSON.stringify(value, replacer, space)`:

* Если значение не может быть преобразовано в JSON-формат, то возвращается `undefined`.
* Для объектов `JSON.stringify` включает только собственные и перебираемые свойства.
* Свойства, значения которых не могут быть преобразованы попросту игнорируются.
* Неподдерживаемые значения в массивах преобразуются в `null`.
* При сериализации объекта вызывается его метод `toJSON`. Если такого метода нет – перечисляются его свойства, кроме функций.

```javascript
> JSON.stringify(function () {})
undefined

> JSON.stringify({ foo: function () {} })
'{}'
> JSON.stringify([ function () {} ])
'[null]'

> JSON.stringify({ toJSON: function () { return 'Cool' } })
'"Cool"'
```

Метод `toJSON` принимает один параметр `key`, отражающий где находится текущий объект относительно родительского:

* корень объекта - пустая строка
* значение свойства -- ключ свойства
* элемент массива - индекс элемента

## `JSON.parse()`

Функция `JSON.parse(text, reviver?)` разбирает текст в формате JSON и возвращает JavaScript значение. Опциональный параметр `reviver?` является функцией формата `function(key, value)`, вызываемой при посещении определенного узла JSON-документа.

При конвертации объекта в JSON и обратно символы никак не обрабатываются и не сохраняются. Для их сохранения нужно заменять символы на специальные идентификаторы в фазе преобразования в JSON, а так же восстанавливать символы по идентификаторам в при обратном преобразовании.

```javascript
function symbolReplacer(key, value) {
  if (typeof value === "symbol") {
    return "@@" + Symbol.keyFor(value) + "@@";
  }
  return value;
}

const MY_SYMBOL = Symbol.for("http://example.com/my_symbol");
let obj = { myKey: MY_SYMBOL };

let str = JSON.stringify(obj, symbolReplacer);
console.log(str);
// {"myKey":"@@http://example.com/my_symbol@@"}
```

Обратный процесс:

```javascript
onst REGEX_SYMBOL_STRING = /^@@(.*)@@$/;
function symbolReviver(key, value) {
    if (typeof value === 'string') {
        let match = REGEX_SYMBOL_STRING.test(value);
        if (match) {
            let symbolKey = match[1];
            return Symbol.for(symbolKey);
        }
    }
    return value;
}

let parsed = JSON.parse(str, symbolReviver);
console.log(parse);
```
