Spec-Zone.ru › JavaScript

JSON

Базовый уровень Широко доступно

Эта функция хорошо зарекомендовала себя и работает на многих устройствах и версиях браузеров. Она доступна в браузерах с июля 2015 года.

Объект пространства имен JSON содержит статические методы для разбора значений из JavaScript Object Notation (JSON) и преобразования значений в JSON.

Описание

В отличие от большинства глобальных объектов, JSON не является конструктором. Вы не можете использовать его с оператором new или вызывать объект JSON как функцию. Все свойства и методы JSON являются статическими (как и объект Math).

Различия между JavaScript и JSON

JSON — это синтаксис для сериализации объектов, массивов, чисел, строк, булевых значений и null. Он основан на синтаксисе JavaScript, но отличается от JavaScript: большая часть JavaScript — это не JSON. Например:

Объекты и массивы
Имена свойств должны быть строками в двойных кавычках; запятые в конце запрещены.
Числа
Ведущие нули запрещены. Десятичная точка должна сопровождаться как минимум одной цифрой. NaN и Infinity не поддерживаются.

Любой JSON-текст является допустимым выражением JavaScript, но только после ревизии JSON superset. До ревизии U+2028 LINE SEPARATOR и U+2029 PARAGRAPH SEPARATOR разрешены в строковых литералах и ключах свойств в JSON; но такое же использование в строковых литералах JavaScript является SyntaxError.

Другие различия включают разрешение только строк в двойных кавычках и отсутствие поддержки undefined или комментариев. Для тех, кто хочет использовать более удобный для человека формат конфигурации на основе JSON, существует JSON5, используемый компилятором Babel, и более широко используемый YAML.

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

Полная грамматика JSON

Допустимый синтаксис JSON формально определяется следующей грамматикой, выраженной в ABNF, и скопированной из стандарта IETF JSON (RFC):

JSON-text = ws value ws
begin-array     = ws %x5B ws  ; [ left square bracket
begin-object    = ws %x7B ws  ; { left curly bracket
end-array       = ws %x5D ws  ; ] right square bracket
end-object      = ws %x7D ws  ; } right curly bracket
name-separator  = ws %x3A ws  ; : colon
value-separator = ws %x2C ws  ; , comma
ws = *(
     %x20 /              ; Space
     %x09 /              ; Horizontal tab
     %x0A /              ; Line feed or New line
     %x0D                ; Carriage return
     )
value = false / null / true / object / array / number / string
false = %x66.61.6c.73.65   ; false
null  = %x6e.75.6c.6c      ; null
true  = %x74.72.75.65      ; true
object = begin-object [ member *( value-separator member ) ]
         end-object
member = string name-separator value
array = begin-array [ value *( value-separator value ) ] end-array
number = [ minus ] int [ frac ] [ exp ]
decimal-point = %x2E       ; .
digit1-9 = %x31-39         ; 1-9
e = %x65 / %x45            ; e E
exp = e [ minus / plus ] 1*DIGIT
frac = decimal-point 1*DIGIT
int = zero / ( digit1-9 *DIGIT )
minus = %x2D               ; -
plus = %x2B                ; +
zero = %x30                ; 0
string = quotation-mark *char quotation-mark
char = unescaped /
    escape (
        %x22 /          ; "    quotation mark  U+0022
        %x5C /          ; \    reverse solidus U+005C
        %x2F /          ; /    solidus         U+002F
        %x62 /          ; b    backspace       U+0008
        %x66 /          ; f    form feed       U+000C
        %x6E /          ; n    line feed       U+000A
        %x72 /          ; r    carriage return U+000D
        %x74 /          ; t    tab             U+0009
        %x75 4HEXDIG )  ; uXXXX                U+XXXX
escape = %x5C              ; \
quotation-mark = %x22      ; "
unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
HEXDIG = DIGIT / %x41-46 / %x61-66   ; 0-9, A-F, or a-f
       ; HEXDIG equivalent to HEXDIG rule in [RFC5234]
DIGIT = %x30-39            ; 0-9
      ; DIGIT equivalent to DIGIT rule in [RFC5234]

Незначительные пробелы могут присутствовать где угодно, кроме как внутри JSONNumber (числа не должны содержать пробелов) или JSONString (где они интерпретируются как соответствующий символ в строке или вызовут ошибку). Символы табуляции (U+0009), возврата каретки (U+000D), перевода строки (U+000A) и пробела (U+0020) являются единственными допустимыми символами пробелов.

Статические свойства

JSON[Symbol.toStringTag]
Начальное значение свойства [Symbol.toStringTag] — это строка "JSON". Это свойство используется в Object.prototype.toString().

Статические методы

JSON.isRawJSON()
Проверяет, является ли значение объектом, возвращенным JSON.rawJSON().
JSON.parse()
Разбирает часть текстовой строки как JSON, при желании преобразуя полученное значение и его свойства, и возвращает значение.
JSON.rawJSON()
Создает объект "сырого JSON", содержащий фрагмент JSON-текста. При сериализации в JSON, объект сырого JSON обрабатывается так, как если бы он уже был фрагментом JSON. Этот текст должен быть действительным JSON.
JSON.stringify()
Возвращает JSON-строку, соответствующую указанному значению, при желании включая только определенные свойства или заменяя значения свойств заданным пользователем способом.

Примеры

Пример JSON

{
  "browsers": {
    "firefox": {
      "name": "Firefox",
      "pref_url": "about:config",
      "releases": {
        "1": {
          "release_date": "2004-11-09",
          "status": "retired",
          "engine": "Gecko",
          "engine_version": "1.7"
        }
      }
    }
  }
}

Вы можете использовать метод JSON.parse() для преобразования приведенной выше JSON-строки в объект JavaScript:

const jsonText = `{
  "browsers": {
    "firefox": {
      "name": "Firefox",
      "pref_url": "about:config",
      "releases": {
        "1": {
          "release_date": "2004-11-09",
          "status": "retired",
          "engine": "Gecko",
          "engine_version": "1.7"
        }
      }
    }
  }
}`;

console.log(JSON.parse(jsonText));

Потерянная сериализация чисел

JSON может содержать числовые литералы произвольной точности. Однако невозможно точно представить все JSON-числа в JavaScript, поскольку JavaScript использует представление с плавающей запятой, которое имеет фиксированную точность. Например, 12345678901234567890 === 12345678901234567000 в JavaScript, потому что они имеют одинаковое представление с плавающей запятой. Это означает, что нет числа JavaScript, которое точно соответствует 12345678901234567890 JSON-числу.

Предположим, у вас есть точное представление некоторого числа (либо через BigInt, либо через пользовательскую библиотеку):

const data = {
  // Using a BigInt here to store the exact value,
  // but it can also be a custom high-precision number library,
  // if the number might not be an integer.
  gross_gdp: 12345678901234567890n,
};

Вы хотите сериализовать его, а затем разобрать до того же точного числа. Существует несколько сложностей:

  • При сериализации, чтобы получить число в JSON, вы должны передать число в JSON.stringify, либо через функцию replacer, либо через метод toJSON. Но в любом случае, вы уже потеряли точность при преобразовании числа. Если вы передадите строку в JSON.stringify, она будет сериализована как строка, а не как число.
  • При разборе не все числа могут быть представлены точно. Например, JSON.parse("12345678901234567890") возвращает 12345678901234568000, потому что число округляется до ближайшего представимого числа. Даже если вы используете функцию reviver, число уже будет округлено до вызова функции reviver.

В общем, существует два способа обеспечить, чтобы числа были без потерь преобразованы в JSON и разобраны обратно: один включает JSON-число, другой — JSON-строку. JSON — это формат обмена данными, поэтому если вы используете JSON, вы, вероятно, обмениваетесь данными с другой системой (HTTP-запрос, сохранение в базе данных и т. д.). Лучшее решение зависит от принимающей системы.

Использование JSON-строк

Если принимающая система не обладает такими же возможностями обработки JSON, как JavaScript, и не поддерживает числа высокой точности, возможно, вы захотите сериализовать число как строку, а затем обрабатывать его как строку на принимающей стороне. Это также единственный вариант в более старом JavaScript.

Чтобы указать, как пользовательские типы данных (включая BigInt) должны быть сериализованы в JSON, добавьте метод toJSON к вашему типу данных или используйте функцию replacer из JSON.stringify().

// Using toJSON() method
BigInt.prototype.toJSON = function () {
  return this.toString();
};
const str1 = JSON.stringify(data);

// Using JSON.stringify() with replacer
const str2 = JSON.stringify(data, (key, value) => {
  if (key === "gross_gdp") {
    return value.toString();
  }
  return value;
});

В любом случае, JSON-текст будет выглядеть как {"gross_gdp":"12345678901234567890"}, где значение является строкой, а не числом. Затем, на принимающей стороне, вы можете разобрать JSON и обработать строку.

Использование JSON-чисел

Если получатель этого сообщения нативно поддерживает числа высокой точности (например, Python-целые числа), передача чисел как JSON-чисел, очевидно, лучше, поскольку они могут быть напрямую разобраны в тип высокой точности вместо разбора строки из JSON, а затем разбора числа из строки. В JavaScript вы можете сериализовать произвольные типы данных в JSON-числа, не производя сначала числовое значение (что приводит к потере точности), используя JSON.rawJSON() для точного указания исходного JSON-текста.

// Using toJSON() method
BigInt.prototype.toJSON = function () {
  return JSON.rawJSON(this.toString());
};
const str1 = JSON.stringify(data);

// Using JSON.stringify() with replacer
const str2 = JSON.stringify(data, (key, value) => {
  if (key === "gross_gdp") {
    return JSON.rawJSON(value.toString());
  }
  return value;
});

Текст, переданный в JSON.rawJSON, обрабатывается так, как если бы он уже был фрагментом JSON, поэтому он не будет сериализован снова как строка. Следовательно, JSON-текст будет выглядеть как {"gross_gdp":12345678901234567890}, где значение — число. Этот JSON затем может быть разобран получателем без дополнительной обработки, при условии, что принимающая система не имеет тех же ограничений точности, что и JavaScript.

При разборе JSON, содержащего числа высокой точности в JavaScript, будьте предельно осторожны, потому что когда JSON.parse() вызывает функцию reviver, полученное вами значение уже разобрано (и потеряло точность). Вы можете использовать параметр context.source функции JSON.parse() reviver для повторного разбора числа самостоятельно.

const parsedData = JSON.parse(str, (key, value, context) => {
  if (key === "gross_gdp") {
    // Or use the constructor of your custom high-precision number library
    return BigInt(context.source);
  }
  return value;
});
// { gross_gdp: 12345678901234567890n }

Спецификации

Спецификация
Спецификация языка ECMAScript® 2027
# sec-json-object

Совместимость с браузерами

Настольный ПК Мобильный Сервер
Chrome Edge Firefox Opera Safari Chrome Android Firefox for Android Opera Android Safari on iOS Samsung Internet WebView Android WebView on iOS Bun Deno Node.js
JSON
3
12
3.5
10.5
4
18
4
11
4
1.0
4.4
4
1.0.0
1.0
0.10.0
isRawJSON
114
114
135
100
18.4
114
135
76
18.4
23.0
114
18.4
1.1.43
1.33
21.0.0
json_superset
66
79
62
53
12
66
62
47
12
9.0
66
12
1.0.0
1.0
10.0.0
parse
3
12
3.5
10.5
4
18
4
11
4
1.0
4.4
4
1.0.0
1.0
0.10.0
rawJSON
114
114
135
100
18.4
114
135
76
18.4
23.0
114
18.4
1.1.43
1.33
21.0.0
stringify
3
12
3.5
10.5
4
18
4
11
4
1.0
4.4
4
1.0.0
1.0
0.10.0

См. также

  • JSON Diff
  • JSON Beautifier/editor
  • JSON Parser
  • JSON Validator

© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API