JSON
BaselineWidely 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.
TheJSON
namespace object contains static methods for parsing values from and converting values toJavaScript Object Notation (JSON).
Description
Unlike most global objects,JSON
is not a constructor. You cannot use it with thenew
operator or invoke theJSON
object as a function. All properties and methods ofJSON
are static (just like theMath
object).
JavaScript and JSON differences
JSON is a syntax for serializing objects, arrays, numbers, strings, booleans, andnull
. It is based upon JavaScript syntax, but is distinct from #"#objects_and_arrays">Objects and Arrays
Property names must be double-quoted strings;trailing commas are forbidden.
Leading zeros are prohibited. A decimal point must be followed by at least one digit.NaN
andInfinity
are unsupported.
Any JSON text is a valid JavaScript expression, but only after theJSON 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 aSyntaxError
.
Other differences include allowing only double-quoted strings and no support forundefined
or comments. For those who wish to use a more human-friendly configuration format based on JSON, there isJSON5, used by the Babel compiler, and the more commonly usedYAML.
The same text may represent different values in JavaScript object literals vs. JSON as well. For more information, seeObject literal syntax vs. JSON.
Full JSON grammar
Valid JSON syntax is formally defined by the following grammar, expressed inABNF, and copied fromIETF JSON standard (RFC):
JSON-text = object / arraybegin-array = ws %x5B ws ; [ left square bracketbegin-object = ws %x7B ws ; { left curly bracketend-array = ws %x5D ws ; ] right square bracketend-object = ws %x7D ws ; } right curly bracketname-separator = ws %x3A ws ; : colonvalue-separator = ws %x2C ws ; , commaws = *( %x20 / ; Space %x09 / ; Horizontal tab %x0A / ; Line feed or New line %x0D ; Carriage return )value = false / null / true / object / array / number / stringfalse = %x66.61.6c.73.65 ; falsenull = %x6e.75.6c.6c ; nulltrue = %x74.72.75.65 ; trueobject = begin-object [ member *( value-separator member ) ] end-objectmember = string name-separator valuearray = begin-array [ value *( value-separator value ) ] end-arraynumber = [ minus ] int [ frac ] [ exp ]decimal-point = %x2E ; .digit1-9 = %x31-39 ; 1-9e = %x65 / %x45 ; e Eexp = e [ minus / plus ] 1*DIGITfrac = decimal-point 1*DIGITint = zero / ( digit1-9 *DIGIT )minus = %x2D ; -plus = %x2B ; +zero = %x30 ; 0string = quotation-mark *char quotation-markchar = 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+XXXXescape = %x5C ; \quotation-mark = %x22 ; "unescaped = %x20-21 / %x23-5B / %x5D-10FFFFHEXDIG = 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]
Insignificantwhitespace may be present anywhere except within aJSONNumber
(numbers must contain no whitespace) orJSONString
(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 inObject.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
{ "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 theJSON.parse()
method to convert the above JSON string into a JavaScript object:
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 the12345678901234567890
JSON number.
Let's assume you have a exact representation of some number (either viaBigInt
or a custom library):
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 thereplacer
function or via thetoJSON
method. But, in either case, you have already lost precision during number conversion. If you pass a string toJSON.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")
returns12345678901234568000
because the number is rounded to the nearest representable number. Even if you use areviver
function, the number will already be rounded before thereviver
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 acommunication 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 (includingBigInt
) should be serialized to JSON, either add atoJSON
method to your data type, or use thereplacer
function ofJSON.stringify()
.
// Using toJSON() methodBigInt.prototype.toJSON = function () { return this.toString();};const str1 = JSON.stringify(data);// Using JSON.stringify() with replacerconst 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 usingJSON.rawJSON()
to precisely specify what the JSON source text should be.
// Using toJSON() methodBigInt.prototype.toJSON = function () { return JSON.rawJSON(this.toString());};const str1 = JSON.stringify(data);// Using JSON.stringify() with replacerconst str2 = JSON.stringify(data, (key, value) => { if (key === "gross_gdp") { return JSON.rawJSON(value.toString()); } return value;});
The text passed toJSON.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 whenJSON.parse()
invokes thereviver
function, the value you receive is already parsed (and has lost precision). You can use thecontext.source
parameter of theJSON.parse()
reviver
function to re-parse the number yourself.
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® 2026 Language Specification # sec-json-object |