JSON

Baseline Widely available *

This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.

* Some parts of this feature may have varying levels of support.

The JSON namespace object contains static methods for parsing values from and converting values to JavaScript Object Notation (JSON).

Description

Unlike most global objects, JSON is not a constructor. You cannot use it with the new operator or invoke the JSON object as a function. All properties and methods of JSON are static (just like the Math object).

JavaScript and JSON differences

JSON is a syntax for serializing objects, arrays, numbers, strings, booleans, and null. It is based upon JavaScript syntax, but is distinct from JavaScript: most of JavaScript is not JSON. For example:

Objects and Arrays

Property names must be double-quoted strings; trailing commas are forbidden.

Numbers

Leading zeros are prohibited. A decimal point must be followed by at least one digit. NaN and Infinity are unsupported.

Any JSON text is a valid JavaScript expression, but only after the JSON superset revision. Before the revision, U+2028 LINE SEPARATOR and U+2029 PARAGRAPH SEPARATOR are allowed in string literals and property keys in JSON; but the same use in JavaScript string literals is a SyntaxError.

Other differences include allowing only double-quoted strings and no support for undefined or comments. For those who wish to use a more human-friendly configuration format based on JSON, there is JSON5, used by the Babel compiler, and the more commonly used YAML.

The same text may represent different values in JavaScript object literals vs. JSON as well. For more information, see Object literal syntax vs. JSON.

Full JSON grammar

Valid JSON syntax is formally defined by the following grammar, expressed in ABNF, and copied from IETF JSON standard (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]

Insignificant whitespace may be present anywhere except within a JSONNumber (numbers must contain no whitespace) or JSONString (where it is interpreted as the corresponding character in the string, or would cause an error). The tab (U+0009), carriage return (U+000D), line feed (U+000A), and space (U+0020) characters are the only valid whitespace characters.

Static properties

JSON[Symbol.toStringTag]

The initial value of the [Symbol.toStringTag] property is the string "JSON". This property is used in Object.prototype.toString().

Static methods

JSON.isRawJSON()

Tests whether a value is an object returned by JSON.rawJSON().

JSON.parse()

Parse a piece of string text as JSON, optionally transforming the produced value and its properties, and return the value.

JSON.rawJSON()

Creates a "raw JSON" object containing a piece of JSON text. When serialized to JSON, the raw JSON object is treated as if it is already a piece of JSON. This text is required to be valid JSON.

JSON.stringify()

Return a JSON string corresponding to the specified value, optionally including only certain properties or replacing property values in a user-defined manner.

Examples

Example 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"
        }
      }
    }
  }
}

You can use the JSON.parse() method to convert the above JSON string into a JavaScript object:

js
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));

Lossless number serialization

JSON can contain number literals of arbitrary precision. However, it is not possible to represent all JSON numbers exactly in JavaScript, because JavaScript uses floating point representation which has a fixed precision. For example, 12345678901234567890 === 12345678901234567000 in JavaScript because they have the same floating point representation. This means there is no JavaScript number that corresponds precisely to the 12345678901234567890 JSON number.

Let's assume you have an exact representation of some number (either via BigInt or a custom library):

js
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,
};

You want to serialize it and then parse to the same exact number. There are several difficulties:

  • On the serialization side, in order to obtain a number in JSON, you have to pass a number to JSON.stringify, either via the replacer function or via the toJSON method. But, in either case, you have already lost precision during number conversion. If you pass a string to JSON.stringify, it will be serialized as a string, not a number.
  • On the parsing side, not all numbers can be represented exactly. For example, JSON.parse("12345678901234567890") returns 12345678901234568000 because the number is rounded to the nearest representable number. Even if you use a reviver function, the number will already be rounded before the reviver function is called.

There are, in general, two ways to ensure that numbers are losslessly converted to JSON and parsed back: one involves a JSON number, another involves a JSON string. JSON is a communication format, so if you use JSON, you are likely communicating with another system (HTTP request, storing in database, etc.). The best solution to choose depends on the recipient system.

Using JSON strings

If the recipient system does not have same JSON-handling capabilities as JavaScript, and does not support high precision numbers, you may want to serialize the number as a string, and then handle it as a string on the recipient side. This is also the only option in older JavaScript.

To specify how custom data types (including BigInt) should be serialized to JSON, either add a toJSON method to your data type, or use the replacer function of JSON.stringify().

js
// 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;
});

In either case, the JSON text will look like {"gross_gdp":"12345678901234567890"}, where the value is a string, not a number. Then, on the recipient side, you can parse the JSON and handle the string.

Using JSON numbers

If the recipient of this message natively supports high precision numbers (such as Python integers), passing numbers as JSON numbers is obviously better, because they can directly parse to the high precision type instead of parsing a string from JSON, and then parsing a number from the string. In JavaScript, you can serialize arbitrary data types to JSON numbers without producing a number value first (resulting in loss of precision) by using JSON.rawJSON() to precisely specify what the JSON source text should be.

js
// 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;
});

The text passed to JSON.rawJSON is treated as if it is already a piece of JSON, so it won't be serialized again as a string. Therefore, the JSON text will look like {"gross_gdp":12345678901234567890}, where the value is a number. This JSON can then be parsed by the recipient without any extra processing, provided that the recipient system does not have the same precision limitations as JavaScript.

When parsing JSON containing high-precision numbers in JavaScript, take extra care because when JSON.parse() invokes the reviver function, the value you receive is already parsed (and has lost precision). You can use the context.source parameter of the JSON.parse() reviver function to re-parse the number yourself.

js
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 }

Specifications

Specification
ECMAScript® 2027 Language Specification
# sec-json-object

Browser compatibility

desktop mobile server
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
Chrome – Full support
Chrome 3 (Release date: 2009-09-15)
footnote Full support
Edge – Full support
Edge 12 (Release date: 2015-07-29)
footnote Full support
Firefox – Full support
Firefox 3.5 (Release date: 2009-06-30)
footnote Full support
Opera – Full support
Opera 10.5 (Release date: 2010-03-02)
footnote Full support
Safari – Full support
Safari 4 (Release date: 2009-06-08)
footnote Full support
Chrome Android – Full support
Chrome Android 18 (Release date: 2012-06-27)
footnote Full support
Firefox for Android – Full support
Firefox for Android 4 (Release date: 2011-03-29)
footnote Full support
Opera Android – Full support
Opera Android 11 (Release date: 2011-03-22)
footnote Full support
Safari on iOS – Full support
Safari on iOS 4 (Release date: 2010-06-21)
footnote Full support
Samsung Internet – Full support
Samsung Internet 1 (Release date: 2013-04-27)
footnote Full support
WebView Android – Full support
WebView Android 4.4 (Release date: 2013-12-09)
footnote Full support
WebView on iOS – Full support
WebView on iOS 4 (Release date: 2010-06-21)
footnote Full support
Bun – Full support
Bun 1 (Release date: 2023-09-08)
footnote Full support
Deno – Full support
Deno 1 (Release date: 2020-05-13)
footnote Full support
Node.js – Full support
Node.js 0.10 (Release date: 2013-03-11)
footnote Full support
isRawJSON
Chrome – Full support
Chrome 114 (Release date: 2023-05-30)
footnote Full support
Edge – Full support
Edge 114 (Release date: 2023-06-02)
footnote Full support
Firefox – Full support
Firefox 135 (Release date: 2025-02-04)
footnote Full support
Opera – Full support
Opera 100 (Release date: 2023-06-29)
footnote Full support
Safari – Full support
Safari 18.4 (Release date: 2025-03-31)
footnote Full support
Chrome Android – Full support
Chrome Android 114 (Release date: 2023-05-30)
footnote Full support
Firefox for Android – Full support
Firefox for Android 135 (Release date: 2025-02-04)
footnote Full support
Opera Android – Full support
Opera Android 76 (Release date: 2023-06-26)
footnote Full support
Safari on iOS – Full support
Safari on iOS 18.4 (Release date: 2025-03-31)
footnote Full support
Samsung Internet – Full support
Samsung Internet 23 (Release date: 2023-10-18)
footnote Full support
WebView Android – Full support
WebView Android 114 (Release date: 2023-05-30)
footnote Full support
WebView on iOS – Full support
WebView on iOS 18.4 (Release date: 2025-03-31)
footnote Full support
Bun – Full support
Bun 1.1.43 (Release date: 2025-01-08)
footnote Full support
Deno – Full support
Deno 1.33 (Release date: 2023-04-28)
footnote Full support
Node.js – Full support
Node.js 21 (Release date: 2023-10-17)
footnote Full support
JavaScript is a superset of JSON
Chrome – Full support
Chrome 66 (Release date: 2018-04-17)
footnote Full support
Edge – Full support
Edge 79 (Release date: 2020-01-15)
footnote Full support
Firefox – Full support
Firefox 62 (Release date: 2018-09-05)
footnote Full support
Opera – Full support
Opera 53 (Release date: 2018-05-10)
footnote Full support
Safari – Full support
Safari 12 (Release date: 2018-09-17)
footnote Full support
Chrome Android – Full support
Chrome Android 66 (Release date: 2018-04-17)
footnote Full support
Firefox for Android – Full support
Firefox for Android 62 (Release date: 2018-09-05)
footnote Full support
Opera Android – Full support
Opera Android 47 (Release date: 2018-07-23)
footnote Full support
Safari on iOS – Full support
Safari on iOS 12 (Release date: 2018-09-17)
footnote Full support
Samsung Internet – Full support
Samsung Internet 9 (Release date: 2018-09-15)
footnote Full support
WebView Android – Full support
WebView Android 66 (Release date: 2018-04-17)
footnote Full support
WebView on iOS – Full support
WebView on iOS 12 (Release date: 2018-09-17)
footnote Full support
Bun – Full support
Bun 1 (Release date: 2023-09-08)
footnote Full support
Deno – Full support
Deno 1 (Release date: 2020-05-13)
footnote Full support
Node.js – Full support
Node.js 10 (Release date: 2018-04-24)
footnote Full support
parse
Chrome – Full support
Chrome 3 (Release date: 2009-09-15)
footnote Full support
Edge – Full support
Edge 12 (Release date: 2015-07-29)
footnote Full support
Firefox – Full support
Firefox 3.5 (Release date: 2009-06-30)
footnote Full support
Opera – Full support
Opera 10.5 (Release date: 2010-03-02)
footnote Full support
Safari – Full support
Safari 4 (Release date: 2009-06-08)
footnote Full support
Chrome Android – Full support
Chrome Android 18 (Release date: 2012-06-27)
footnote Full support
Firefox for Android – Full support
Firefox for Android 4 (Release date: 2011-03-29)
footnote Full support
Opera Android – Full support
Opera Android 11 (Release date: 2011-03-22)
footnote Full support
Safari on iOS – Full support
Safari on iOS 4 (Release date: 2010-06-21)
footnote Full support
Samsung Internet – Full support
Samsung Internet 1 (Release date: 2013-04-27)
footnote Full support
WebView Android – Full support
WebView Android 4.4 (Release date: 2013-12-09)
footnote Full support
WebView on iOS – Full support
WebView on iOS 4 (Release date: 2010-06-21)
footnote Full support
Bun – Full support
Bun 1 (Release date: 2023-09-08)
footnote Full support
Deno – Full support
Deno 1 (Release date: 2020-05-13)
footnote Full support
Node.js – Full support
Node.js 0.10 (Release date: 2013-03-11)
footnote Full support
Reviver has context parameter
Chrome – Full support
Chrome 114 (Release date: 2023-05-30)
footnote Full support
Edge – Full support
Edge 114 (Release date: 2023-06-02)
footnote Full support
Firefox – Full support
Firefox 135 (Release date: 2025-02-04)
footnote Full support
Opera – Full support
Opera 100 (Release date: 2023-06-29)
footnote Full support
Safari – Full support
Safari 18.4 (Release date: 2025-03-31)
footnote Full support
Chrome Android – Full support
Chrome Android 114 (Release date: 2023-05-30)
footnote Full support
Firefox for Android – Full support
Firefox for Android 135 (Release date: 2025-02-04)
footnote Full support
Opera Android – Full support
Opera Android 76 (Release date: 2023-06-26)
footnote Full support
Safari on iOS – Full support
Safari on iOS 18.4 (Release date: 2025-03-31)
footnote Full support
Samsung Internet – Full support
Samsung Internet 23 (Release date: 2023-10-18)
footnote Full support
WebView Android – Full support
WebView Android 114 (Release date: 2023-05-30)
footnote Full support
WebView on iOS – Full support
WebView on iOS 18.4 (Release date: 2025-03-31)
footnote Full support
Bun – Full support
Bun 1.1.43 (Release date: 2025-01-08)
footnote Full support
Deno – Full support
Deno 1.33 (Release date: 2023-04-28)
footnote Full support
Node.js – Full support
Node.js 21 (Release date: 2023-10-17)
footnote Full support
rawJSON
Chrome – Full support
Chrome 114 (Release date: 2023-05-30)
footnote Full support
Edge – Full support
Edge 114 (Release date: 2023-06-02)
footnote Full support
Firefox – Full support
Firefox 135 (Release date: 2025-02-04)
footnote Full support
Opera – Full support
Opera 100 (Release date: 2023-06-29)
footnote Full support
Safari – Full support
Safari 18.4 (Release date: 2025-03-31)
footnote Full support
Chrome Android – Full support
Chrome Android 114 (Release date: 2023-05-30)
footnote Full support
Firefox for Android – Full support
Firefox for Android 135 (Release date: 2025-02-04)
footnote Full support
Opera Android – Full support
Opera Android 76 (Release date: 2023-06-26)
footnote Full support
Safari on iOS – Full support
Safari on iOS 18.4 (Release date: 2025-03-31)
footnote Full support
Samsung Internet – Full support
Samsung Internet 23 (Release date: 2023-10-18)
footnote Full support
WebView Android – Full support
WebView Android 114 (Release date: 2023-05-30)
footnote Full support
WebView on iOS – Full support
WebView on iOS 18.4 (Release date: 2025-03-31)
footnote Full support
Bun – Full support
Bun 1.1.43 (Release date: 2025-01-08)
footnote Full support
Deno – Full support
Deno 1.33 (Release date: 2023-04-28)
footnote Full support
Node.js – Full support
Node.js 21 (Release date: 2023-10-17)
footnote Full support
stringify
Chrome – Full support
Chrome 3 (Release date: 2009-09-15)
footnote Full support
Edge – Full support
Edge 12 (Release date: 2015-07-29)
footnote Full support
Firefox – Full support
Firefox 3.5 (Release date: 2009-06-30)
footnote Full support
Opera – Full support
Opera 10.5 (Release date: 2010-03-02)
footnote Full support
Safari – Full support
Safari 4 (Release date: 2009-06-08)
footnote Full support
Chrome Android – Full support
Chrome Android 18 (Release date: 2012-06-27)
footnote Full support
Firefox for Android – Full support
Firefox for Android 4 (Release date: 2011-03-29)
footnote Full support
Opera Android – Full support
Opera Android 11 (Release date: 2011-03-22)
footnote Full support
Safari on iOS – Full support
Safari on iOS 4 (Release date: 2010-06-21)
footnote Full support
Samsung Internet – Full support
Samsung Internet 1 (Release date: 2013-04-27)
footnote Full support
WebView Android – Full support
WebView Android 4.4 (Release date: 2013-12-09)
footnote Full support
WebView on iOS – Full support
WebView on iOS 4 (Release date: 2010-06-21)
footnote Full support
Bun – Full support
Bun 1 (Release date: 2023-09-08)
footnote Full support
Deno – Full support
Deno 1 (Release date: 2020-05-13)
footnote Full support
Node.js – Full support
Node.js 0.10 (Release date: 2013-03-11)
footnote Full support
Strings are escaped to well-formed UTF-8
Chrome – Full support
Chrome 72 (Release date: 2019-01-29)
footnote Full support
Edge – Full support
Edge 79 (Release date: 2020-01-15)
footnote Full support
Firefox – Full support
Firefox 64 (Release date: 2018-12-11)
footnote Full support
Opera – Full support
Opera 60 (Release date: 2019-04-09)
footnote Full support
Safari – Full support
Safari 12.1 (Release date: 2019-03-25)
footnote Full support
Chrome Android – Full support
Chrome Android 72 (Release date: 2019-01-29)
footnote Full support
Firefox for Android – Full support
Firefox for Android 64 (Release date: 2018-12-11)
footnote Full support
Opera Android – Full support
Opera Android 50 (Release date: 2019-02-18)
footnote Full support
Safari on iOS – Full support
Safari on iOS 12.2 (Release date: 2019-03-25)
footnote Full support
Samsung Internet – Full support
Samsung Internet 11 (Release date: 2019-12-05)
footnote Full support
WebView Android – Full support
WebView Android 72 (Release date: 2019-01-29)
footnote Full support
WebView on iOS – Full support
WebView on iOS 12.2 (Release date: 2019-03-25)
footnote Full support
Bun – Full support
Bun 1 (Release date: 2023-09-08)
footnote Full support
Deno – Full support
Deno 1 (Release date: 2020-05-13)
footnote Full support
Node.js – Full support
Node.js 12 (Release date: 2019-04-23)
footnote Full support

Legend

Tip: you can click/tap on a cell for more information.

Full support
Full support

See also