ECMAScript | Объект JSON (The JSON Object)

Объект JSON:

  • является %JSON%.
  • является начальным значением свойства «JSON» для глобального объекта.
  • это обычный объект.
  • содержит две функции, parse и stringify, которые используются для анализа и построения текстов JSON.
  • имеет внутренний слот [[Prototype]], значение которого равно %Object.prototype%.
  • не имеет внутреннего метода [[Construct]]; его нельзя использовать в качестве конструктора с оператором new.
  • не имеет внутреннего метода [[Call]]; его нельзя вызвать как функцию.

Формат обмена данными JSON определен в ECMA-404. Формат обмена JSON, используемый в этой спецификации, в точности соответствует описанию ECMA-404. Соответствующие реализации JSON.parse и JSON.stringify должны поддерживать точный формат обмена, описанный в спецификации ECMA-404, без каких-либо удалений или расширений формата.

25.5.1 JSON.parse ( text [ , reviver ] )

Функция синтаксического анализа parse анализирует текст JSON (строка в формате JSON) и выдает значение ECMAScript. Формат JSON представляет литералы, массивы и объекты с синтаксисом, аналогичным синтаксису для литералов ECMAScript, инициализаторов массивов и инициализаторов объектов. После синтаксического анализа объекты JSON реализуются как объекты ECMAScript. Массивы JSON реализованы как экземпляры массива ECMAScript. Строки, числа, логические значения и значения null для JSON реализованы как Строки, Числа, Логические значения и значения null для ECMAScript.

Необязательный параметр reviver — это функция, которая принимает два параметра: ключ и значение (key и value). Он может фильтровать и преобразовывать результаты. Он вызывается с каждой парой ключ/значение, созданной в результате синтаксического анализа, и его возвращаемое значение используется вместо исходного значения. Если он возвращает то, что получил, структура не изменяется. Если он возвращает значение undefined, свойство удаляется из результата.

1. Пусть jsonString будет ? ToString(text).
2. Разобрать синтаксически ! StringToCodePoints(jsonString) в виде текста JSON, как указано в ECMA-404. Вызывайте исключение SyntaxError, если это недопустимый текст JSON, как определено в этой спецификации.
3. Пусть scriptString представляет собой конкатенацию строк "(", jsonString и ");".
4. Пусть сценарий script будет ParseText(! StringToCodePoints(scriptString), Script).
5. ПРИМЕЧАНИЕ. Правила ранней ошибки, определенные в 13.2.5.1, имеют специальную обработку для вышеупомянутого вызова ParseText.
6. Утверждено: сценарий script является Узлом Синтаксического Анализа.
7. Пусть завершение completion будет результатом оценки сценария script.
8. ПРИМЕЧАНИЕ. Семантика PropertyDefinitionEvaluation, определенная в 13.2.5.5, имеет специальную обработку для вышеуказанной оценки.
9. Пусть unfiltered будет completion.[[Value]].
10. Утверждено: unfiltered - это либо String, Number, Boolean, Null, либо Object, который определяется либо ArrayLiteral, либо ObjectLiteral.
11. Если IsCallable(reviver) является true (истинно), то
  а. Пусть root будет ! OrdinaryObjectCreate(%Object.prototype%).
  b. Пусть rootName будет пустой Строкой.
  c. Выполнить ! CreateDataPropertyOrThrow(root, rootName, unfiltered).
  d. Вернуть ? InternalizeJSONProperty(root, rootName, reviver).
12. Иначе,
  а. Вернуть unfiltered.

Свойство длины «length» функции синтаксического анализа parse равно 2𝔽.

Примечание

Допустимый текст JSON — это подмножество синтаксиса ECMAScript PrimaryExpression. На шаге 2 проверяется, соответствует ли jsonString этому подмножеству, а на шаге 10 утверждается, что этот синтаксический анализ и оценка возвращают значение соответствующего типа.

Однако, поскольку 13.2.5.5 ведет себя по-разному во время JSON.parse, один и тот же исходный текст может давать разные результаты при оценке как PrimaryExpression, а не как JSON. Кроме того, ранняя ошибка для повторяющихся свойств «__proto__» в объектных литералах, которая также не применяется во время JSON.parse, означает, что не все тексты, принятые JSON.parse, действительны как PrimaryExpression, несмотря на соответствие грамматики.

 

25.5.1.1 InternalizeJSONProperty ( holder, name, reviver )

Абстрактная операция InternalizeJSONProperty принимает аргументы: держатель holder (Объект), имя name (Строка) и средство восстановления reviver (Объект Функции).

Примечание 1

Этот алгоритм намеренно не генерирует исключение, если [[Delete]] или CreateDataProperty возвращают false.

При вызове она выполняет следующие шаги:

1. Пусть val будет ? Получить(holder, name).
2. Если Тип(val) является Объект, то
  а. Пусть isArray будет ? IsArray(val).
  b. Если isArray является true (истинно), то
    i. Пусть I будет 0.
    ii. Пусть len будет ? LengthOfArrayLike(val).
    iii. Повторяйте, пока I < len,
      1. Пусть prop будет ! ToString(𝔽(I)).
      2. Пусть newElement будет ? InternalizeJSONProperty(val, prop, reviver).
      3. Если newElement является undefined (не определен), тогда
        а. Выполнить ? val. [[Delete]](prop).
      4. Иначе,
        а. Выполнить ? CreateDataProperty(val, prop, newElement).
      5. Установите I в I + 1.
  c. Иначе,
    i. Пусть keys будут? EnumerableOwnPropertyNames(val, key).
    ii. Для каждой строки P из ключей keys  выполните
      1. Пусть newElement будет ? InternalizeJSONProperty(val, P, reviver).
      2. Если newElement является undefined (не определен), тогда
        а. Выполнить ? val.[[Delete]](P).
      3. Иначе,
        а. Выполнить ? CreateDataProperty(val, P, newElement).
3. Вернуть ? Вызов(reviver, holder, « name, val »).

Соответствующей реализации JSON.parse не разрешено расширять грамматики JSON. Если реализация желает поддерживать изменённый или расширенный формат обмена JSON, она должна сделать это, определив другую функцию синтаксического анализа.

Примечание 2

В случае, когда в объекте есть повторяющиеся Строки имен, лексически предшествующие значения для одного и того же ключа должны быть перезаписаны.

25.5.2 JSON.stringify ( value [ , replacer [ , space ] ] )

Функция stringify возвращает Строку в формате JSON с кодировкой UTF-16, представляющую значение ECMAScript, или значение undefined. Может принимать три параметра.

Параметр value — это значение ECMAScript, которое обычно является объектом (object) или массивом (array), хотя также может быть строкой (String), Boolean, Number или null.

Необязательный параметр replacer — это либо функция, которая изменяет способ преобразования объектов и массивов в строку, либо массив строк и чисел, который действует как список включения для выбора свойств объекта, которые будут преобразованы в строку.

Необязательный параметр space — это строка или число, которые позволяют вставлять в результат пустое пространство для улучшения читабельности.

Вот шаги по преобразованию объекта в строку:

1. Пусть stack будет новым пустым Списком.
2. Пусть indent будет пустой Строкой.
3. Пусть PropertyList и ReplacerFunction будут undefined (не определены).
4. Если Type(replacer) является Object, то
  а. Если IsCallable(replacer) является true (истинно), то
    i. Установите ReplacerFunction на replacer.
  b. Иначе,
    i. Пусть isArray будет ? IsArray(replacer).
    ii. Если isArray является true (истинно), то
      1. Установите для PropertyList новый пустой Список.
      2. Пусть len будет ? LengthOfArrayLike(replacer).
      3. Пусть k равно 0.
      4. Повторите, пока k < len,
        а. Пусть prop будет ! ToString(𝔽(k)).
        b. Пусть v будет ? Получить(replacer, prop).
        c. Пусть item будет undefined (не определен).
        d. Если Тип(v) равен String, установите для item значение v.
        e. В противном случае, если Тип(v) является Числом, установите для item значение ! ToString(v).
        f. Иначе, если Тип(v) является Объектом, то
          i. Если v имеет внутренний слот [[StringData]] или [[NumberData]], установите для item значение ? ToString(v).
        g. Если item является undefined (не определен) и item в настоящее время не является элементом PropertyList, тогда
          i. Добавить item в конец PropertyList.
        h. Установите k на k + 1.
5. Если Тип(space) - Объект, то
  а. Если у space есть внутренний слот [[NumberData]], то
    i. Установить space на ? ToNumber(space).
  b. Иначе, если в space есть внутренний слот [[StringData]], тогда
    i. Установить space на ? ToString(space).
6. Если Тип(space) является Числом, тогда
  а. Пусть spaceMV будет ! ToIntegerOrInfinity(space).
  b. Установите для spaceMV значение min(10, spaceMV).
  c. Если spaceMV < 1, пусть gap будет пустой Строкой; в противном случае пусть gap будет значением String, содержащим вхождения spaceMV кодовой единицы 0x0020(ПРОБЕЛ).
7. Иначе, если Тип(space) равен Строке, тогда
  а. Если длина space равна 10 или меньше, пусть gap будет space; в противном случае пусть gap будет подстрокой space от 0 до 10.
8. Иначе,
  а. Пусть gap будет пустой Строкой.
9. Пусть wrapper будет ! OrdinaryObjectCreate(%Object.prototype%).
10. Выполнить ! CreateDataPropertyOrThrow(wrapper, пустая строка, value).
11. Пусть состоянием state будет Запись {[[ReplacerFunction]]: ReplacerFunction, [[Stack]]: stack, [[Indent]]: indent, [[Gap]]: gap, [[PropertyList]]: PropertyList}.
12. Вернуть ? SerializeJSONProperty(state, пустая строка, wrapper).

Свойство «length» функции stringify равно 3𝔽.

Примечание 1

Структуры JSON могут быть вложены на любую глубину, но они должны быть ациклическими. Если value является циклической структурой или содержит ее, то функция stringify должна вызывать исключение TypeError. Это пример значения, которое не может быть преобразовано в строку:

a = [];
a[0] = a;
my_text = JSON.stringify(a); // Это должно вызвать ошибку TypeError.

 

Примечание 2

Символьные примитивные значения отображаются следующим образом:

  • Значение null отображается в тексте JSON как String «null».
  • Значение undefined не отображается.
  • Значение true отображается в тексте JSON как String «true».
  • Значение false отображается в тексте JSON как String «false».

 

Примечание 3

Строковые значения заключаются в единицы кода QUOTATION MARK («). Единицы кода « и \ экранируются префиксами \. Единицы кода управляющих символов заменяются escape-последовательностями \uHHHH или более короткими формами, \b (BACKSPACE), \f (FORM FEED), \n (LINE FEED), \r (CARRIAGE RETURN), \t (CHARACTER TABULATION ).

 

Примечание 4

Конечные числа преобразовываются в строки, как если бы они вызывали ToString(number). NaN и Infinity независимо от знака представлены как строка «null».

 

Примечание 5

Значения, не имеющие представления JSON (например, undefined и функции), не создают String. Вместо этого они производят значение undefined. В массивах эти значения представлены как String строковое «null». В объектах непредставимое значение приводит к тому, что свойство исключается из строкового преобразования.

 

Примечание 6

Объект отображается как U+007B (LEFT CURLY BRACKET), за которым следует ноль или более свойств, разделенных U+002C (COMMA), закрытых U+007D (RIGHT CURLY BRACKET). Свойство — это строка в кавычках, представляющая ключ или имя свойства, U+003A (COLON), а затем строковое значение свойства. Массив отображается как открывающийся U+005B (LEFT SQUARE BRACKET, за которойм следуют ноль или более значений, разделенные U+002C (COMMA), закрытые U+005D (RIGHT SQUARE BRACKET).

 

25.5.2.1 SerializeJSONProperty ( state, key, holder )

Абстрактная операция SerializeJSONProperty принимает аргументы state, key, holder. При вызове она выполняет следующие шаги:

1. Пусть value будет ? Получить(holder, key).
2. Если Тип(value) является Объектом или BigInt, тогда
  а. Пусть toJSON будет ? GetV(value, "toJSON").
  b. Если IsCallable(toJSON) является true (истинно), то
    i. Установить value на ? Вызов(toJSON, value, « key »).
3. Если state.[[ReplacerFunction]] не является undefined, тогда
  а. Установить value на ? Вызов(state.[[ReplacerFunction]], holder, « key, value »).
4. Если Тип(value) - это Объект, то
  а. Если value имеет внутренний слот [[NumberData]], то
    i. Установить value на ? ToNumber(value).
  b. Иначе, если value имеет внутренний слот [[StringData]], тогда
    i. Установить value на ? ToString(value).
  c. Иначе, если value имеет внутренний слот [[BooleanData]], тогда
    i. Установите value в value.[[BooleanData]].
  d. Иначе, если value имеет внутренний слот [[BigIntData]], тогда
    i. Установите value в value.[[BigIntData]].
5. Если value равно null, вернуть "null".
6. Если value является true (истинно), вернуть "true".
7. Если value является false, вернуть "false".
8. Если Тип(value) - Строка, вернуть QuoteJSONString(value).
9. Если Тип(value) - Число, тогда
  а. Если value конечно, верните ! ToString(value).
  b. Вернуть "null".
10. Если Тип(value) - BigInt, выбросить исключение TypeError.
11. Если Тип(value) - это Объект, а IsCallable(value) - false, тогда
  а. Пусть isArray будет ? IsArray(value).
  b. Если isArray является true (истинно), вернуть ? SerializeJSONArray(state, value).
  c. Вернуть ? SerializeJSONObject(state, value).
12. Вернуть undefined.

 

25.5.2.2 QuoteJSONString ( value )

Абстрактная операция QuoteJSONString принимает аргумент value. Она заключает value в кодовые единицы 0x0022 (QUOTATION MARK) и избегает некоторых других кодовых единиц внутри него. Эта операция интерпретирует значение как последовательность кодовых точек в кодировке UTF-16, как описано в разделе 6.1.4. При вызове она выполняет следующие шаги:

1. Пусть product будет значением String, состоящим исключительно из кодовой единицы 0x0022 (QUOTATION MARK).
2. Для каждой кодовой точки C из ! StringToCodePoints(value), сделать
  а. Если C указан в столбце «Кодовая точка» Таблицы 74, то
    i. Установите product для конкатенации строк product и escape-последовательности для C, как указано в столбце «Escape Sequence» соответствующей строки.
  b. В противном случае, если C имеет числовое значение меньше 0x0020(ПРОБЕЛ), или если C имеет такое же числовое значение, как ведущий суррогат или конечный суррогат, то
    i. Пусть unit будет единицей кода, числовое значение которой совпадает с C.
    ii. Установите product для конкатенации строк product и UnicodeEscape(unit).
  c. Иначе,
    i. Установите product на конкатенацию строк product и ! UTF16EncodeCodePoint(C).
3. Установите product на конкатенацию строки product и единицы кода 0x0022 (QUOTATION MARK).
4. Верните product.
Кодовая Точка (Code Point) Имя символа Юникода (Unicode Character Name) Последовательность побега (Escape Sequence)
U+0008 BACKSPACE \b
U+0009 CHARACTER TABULATION \t
U+000A LINE FEED (LF) \n
U+000C FORM FEED (FF) \f
U+000D CARRIAGE RETURN (CR) \r
U+0022 QUOTATION MARK
U+005C REVERSE SOLIDUS \\

 

25.5.2.3 UnicodeEscape ( C )

Абстрактная операция UnicodeEscape принимает аргумент C (кодовую единицу). Она представляет C как escape-последовательность Unicode. При вызове он выполняет следующие шаги:

1. Пусть n будет числовым значением C.
2. Утверждено: n ≤ 0xFFFF.
3. Верните конкатенацию строк:
  кодовый блок 0x005C (REVERSE SOLIDUS)
  "u"
  Строковое представление числа n, отформатированное как четырехзначное шестнадцатеричное число в нижнем регистре, при необходимости дополненное слева нулями

 

25.5.2.4 SerializeJSONObject ( state, value )

Абстрактная операция SerializeJSONObject принимает состояние и значение аргументов. Она сериализует объект. При вызове она выполняет следующие шаги:

1. Если state.[[Stack]] содержит значение, выбросить исключение TypeError, потому что структура циклическая.
2. Добавить value в state.[[Стек]].
3. Пусть stepback будет state.[[Indent]].
4. Установите state.[[Indent]] на конкатенацию строк state.[[Indent]] и state.[[Gap]].
5. Если state.[[PropertyList]] не является undefined, тогда
  а. Пусть K - state.[[PropertyList]].
6. Иначе,
  а. Пусть K будет? EnumerableOwnPropertyNames(value, key).
7. Пусть partial будет новым пустым Списком.
8. Для каждого элемента P из K сделайте
  а. Пусть strP будет ? SerializeJSONProperty(state, P, value).
  b. Если strP не undefined, тогда
    i. Пусть member будет QuoteJSONString(P).
    ii. Установите member для конкатенации строки member и ":".
    iii. Если state.[[Gap]] не является пустой строкой, тогда
      1. Установите member для конкатенации строк элемента и единицы кода 0x0020 (ПРОБЕЛ).
    iv. Установите member для конкатенации строк member и strP.
    v. Добавить member в partial.
9. Если partial является пустым, то
  а. Пусть final будет "{}".
10. Иначе,
  а. Если state.[[Gap]] - это пустая строка, тогда
    i. Пусть properties будет значением String, сформированным путем объединения всех элементов Strings из partial с каждой смежной парой строк, разделенных единицей кода 0x002C (ЗАПЯТАЯ). Запятая не вставляется ни перед первой строкой, ни после последней строки.
    ii. Пусть final будет конкатенацией строк "{", properties и "}".
  b. Иначе,
    i. Пусть separator будет конкатенацией строки кода 0x002C(ЗАПЯТАЯ), кодовой единицы 0x000A(ПОДАЧА СТРОКИ) и state.[[Indent]].
    ii. Пусть properties будет значением String, сформированным путем объединения всех элементов Strings из partial с каждой смежной парой строк, разделенных разделителем. Строка-разделитель не вставляется ни перед первой, ни после последней строки.
    iii. Пусть final будет конкатенацией строк "{", кодовой единицы 0x000A(LINE FEED), state.[[Indent]], свойств, кодовой единицы 0x000A(LINE FEED), stepback и "}".
11. Удалите последний элемент state.[[Stack]].
12. Установите state.[[Indent]] на stepback.
13. Вернуть final.

 

25.5.2.5 SerializeJSONArray ( state, value )

Абстрактная операция SerializeJSONArray принимает аргументы состояние и значение. Она сериализует массив. При вызове он выполняет следующие шаги:

1. Если state.[[Stack]] содержит значение, выбросить исключение TypeError, потому что структура циклическая.
2. Добавить value в state.[[Stack]].
3. Пусть stepback будет state.[[Indent]].
4. Установите state.[[Indent]] на конкатенацию строк состояния.[[Indent]] и state.[[Gap]].
5. Пусть partial будет новым пустым Списком.
6. Пусть len будет ? LengthOfArrayLike(value).
7. Пусть index равен 0.
8. Повторите, пока index < len,
  а. Пусть strP будет ? SerializeJSONProperty(state, ! ToString(𝔽(index)), value).
  b. Если strP является undefined, тогда
    i. Добавьте "null" к partial.
  c. Иначе,
    i. Добавить strP в partial.
  d. Установите index на index + 1.
9. Если partial пусто, то
  а. Пусть final будет "[]".
10. Иначе,
  а. Если state.[[Gap]] - это пустая строка, тогда
    i. Пусть properties будет значением String, сформированным путем объединения всех элементов Strings из partial с каждой смежной парой строк, разделенных единицей кода 0x002C (ЗАПЯТАЯ). Запятая не вставляется ни перед первой строкой, ни после последней строки.
    ii. Пусть final будет конкатенацией строк "[", properties и "]".
  b. Иначе,
    i. Пусть separator будет конкатенацией строки кода 0x002C(ЗАПЯТАЯ), кодовой единицы 0x000A(ПОДАЧА СТРОКИ) и состояния.[[Indent]].
    ii. Пусть properties будет значением String, сформированным путем объединения всех элементов Strings из partial с каждой смежной парой строк, разделенных разделителем. Строка-разделитель не вставляется ни перед первой, ни после последней строки.
    iii. Пусть final будет конкатенацией строк "[", кодовой единицы 0x000A(LINE FEED), state.[[Indent]], свойств, кодовой единицы 0x000A(LINE FEED), stepback и "]".
11. Удалите последний элемент state.[[Stack]].
12. Установите state.[[Indent]] на шаг назад.
13. Вернуть final.
Примечание

Представление массивов включает только элементы от нуля до array.length — 1 включительно. Свойства, ключи которых не являются индексами массива, исключаются из строкового преобразования. Массив оформляется в виде открывающей ЛЕВОЙ КВАДРАТНОЙ СКОБКИ, элементы, разделенные запятой, и закрывающей ПРАВОЙ КВАДРАТНОЙ СКОБКОЙ.

 

25.5.3 JSON [ @@toStringTag ]

Начальным значением свойства @@toStringTag является строковое значение «JSON».

Это свойство имеет атрибуты {[[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true}.

 

Информационные ссылки

Стандарт ECMAScript — Раздел «25.5 The JSON Object» — https://tc39.es/ecma262/#sec-json-object

Поделись записью