en.javascript.info/1-js/7-js-misc/2-json/2-serialize-object-circular/solution.md
2015-03-10 12:36:58 +03:00

64 lines
No EOL
2.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Ответ на первый вопрос
Обычный вызов `JSON.stringify(team)` выдаст ошибку, так как объекты `leader` и `soldier` внутри структуры ссылаются друг на друга.
Формат JSON не предусматривает средств для хранения ссылок.
# Варианты решения
Чтобы превращать такие структуры в JSON, обычно используются два подхода:
<ol>
<li>Добавить в `team` свой код `toJSON`:
```js
team.toJSON = function() {
/* свой код, который может создавать копию объекта без круговых ссылок и передавать управление JSON.stringify */
}
```
При этом, конечно, понадобится и своя функция чтения из JSON, которая будет восстанавливать объект, а затем дополнять его круговыми ссылками.
</li>
<li>Можно учесть возможную проблему в самой структуре, используя вместо ссылок `id`. Как правило, это несложно, ведь на сервере у данных тоже есть идентификаторы.
Изменённая структура может выглядеть так:
```js
var leader = {
id: 12,
name: "Василий Иванович"
};
var soldier = {
id: 51,
name: "Петька"
};
*!*
// поменяли прямую ссылку на ID
leader.soldierId = 51;
soldier.leaderId = 12;
*/!*
var team = {
12: leader,
51: soldier
};
```
..Но действительно ли это решение будет оптимальным? Использовать структуру стало сложнее, и вряд ли это изменение стоит делать лишь из-за JSON. Вот если есть другие преимущества, тогда можно подумать.
</li>
</ol>
Универсальный вариант подхода, описанного выше -- это использование особой реализации JSON, которая не входит в стандарт и поддерживает расширенный формат для поддержки ссылок.
Она, к примеру, есть во фреймворке Dojo.
При вызове `dojox.json.ref.toJson(team)` будет создано следующее строковое представление:
```js
//+ no-beautify
[{"name":"Василий Иванович","soldier":{"name":"Петька","leader":{"$ref":"#0"}}},{"$ref":"#0.soldier"}]
```
Метод разбора такой строки -- также свой: `dojox.json.ref.fromJson`.