JSON.parse()
Обычно JSON используется для обмена данными с сервером.
При получении с сервера данные всегда передаются в виде строки.
Если обработать эти данные при помощи функции JSON.parse(), то они станут объектом JavaScript.
Парсинг данных JSON
Представьте, что с сервера мы получили такой текст:
Используем JavaScript функцию JSON.parse(), чтобы преобразовать этот текст в объект JavaScript:
var obj = JSON.parse('< "name":"John", "age":30, "city":"New York">');
Внимание! Убедитесь, что преобразуемый текст записан в формате JSON, иначе вы получите ошибку синтаксиса.
Используем полученный объект JavaScript на странице:
Получение данных JSON с сервера
Получить данные JSON с сервера можно, например, используя запрос AJAX.
Так как ответ сервера записан в формате JSON, вы можете преобразовать строку в объект JavaScript.
В следующем примере используется XMLHttpRequest, чтобы получить данные с сервера:
var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function() < if (this.readyState == 4 && this.status == 200) < var myObj = JSON.parse(this.responseText); document.getElementById("demo").innerHTML = myObj.name; >>; xmlhttp.open("GET", "json_demo.txt", true); xmlhttp.send();
Массивы как данные JSON
Если функция JSON.parse() используется для парсинга данных JSON, полученных из массива, то будет возвращен массив JavaScript, а не объект.
В следующем примере возвращенные с сервера данные JSON являются массивом:
var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function() < if (this.readyState == 4 && this.status == 200) < var myArr = JSON.parse(this.responseText); document.getElementById("demo").innerHTML = myArr[0]; >>; xmlhttp.open("GET", "json_demo_array.txt", true); xmlhttp.send();
Парсинг дат
Объекты даты и времени (тип Date) нельзя использовать в JSON.
Если вам необходимо включить в данные дату, записывайте ее как строку.
Когда это потребуется, вы сможете преобразовать ее обратно в объект:
var text = '< "name":"John", "birth":"1986-12-14", "city":"New York">'; var obj = JSON.parse(text); obj.birth = new Date(obj.birth); document.getElementById("demo").innerHTML = obj.name + ", " + obj.birth;
Либо можно воспользоваться вторым параметром функции JSON.parse().
В качестве второго параметра передается функция, которая проверяет каждое свойство перед тем, как вернуть его значение.
В следующем примере строка преобразуется в объект даты, при помощи второго параметра JSON.parse():
var text = '< "name":"John", "birth":"1986-12-14", "city":"New York">'; var obj = JSON.parse(text, function (key, value) < if (key == "birth") < return new Date(value); >else < return value; >>); document.getElementById("demo").innerHTML = obj.name + ", " + obj.birth;
Парсинг функций
Функции нельзя использовать в JSON.
Если вам необходимо включить в данные функцию, записывайте ее как строку.
Когда это потребуется, вы сможете преобразовать ее обратно в функцию:
var text = '< "name":"John", "age":"function () ", "city":"New York">'; var obj = JSON.parse(text); obj.age = eval("(" + obj.age + ")"); document.getElementById("demo").innerHTML = obj.name + ", " + obj.age();
Внимание! Следует избегать использования функций в JSON, так как в этом случае теряется их область видимости, а для обратного преобразования приходится использовать функцию eval(), что нежелательно.
Поддержка браузерами
Функция JSON.parse() включена во все основные браузеры и в последний стандарт ECMAScript (JavaScript).
Нельзя просто так взять и распарсить этот JSON на JavaScript
JSON является одним из очень простых, но в то же время эффективных языков для хранения и передачи данных. Он настолько популярен, что, пожалуй, может считаться самым совместимым форматом представления данных в мире. Вероятно, что все современные языки программирования умеют работать с JSON практически из коробки.
Одновременно с этим, JavaScript является одним из наиболее популярных языков программирования и применяется практически везде, начиная от веб-браузеров, заканчивая серверами и инструментами разработки. Также, нужно понимать, что JSON появился напрямую из JavaScript и эти два языка просто созданы друг для друга.
Но что же может пойти не так, спросите Вы? Просто попробуйте распарсить следующий JSON-документ:
Давайте попробуем самый простой способ:
const object = JSON.parse('< "foo": 123456789123456789123 >'); console.log(object.foo); // Outputs: 123456789123456800000
Что же здесь произошло? Очевидно результат выполнения: 123456789123456800000 отличается от оригинального значения из JSON-документа: 123456789123456789123
Дело в том, что указанное число слишком велико, чтобы быть представленным стандартными типами данных, которые можно найти в современных языках программирования. Обычно, самым большим типом данных, который часто поддерживается языками программирования, является unsigned int 64 , т. е. целое 64-битное число без знака (что соответствует размерам регистра современного 64-битного процессора), тогда как наше число требует 67 битов для корректного представления. Это и приводит к потере точности при попытке записать число в память компьютера. И стоит понимать, что это происходит не только с JavaScript, но и со всеми языками программирования, которые имеют ограничение на размер хранимого числа.
Чтобы избежать этой проблемы, как правило, современные языки программирования имеют специальный тип данных, обычно называемый BigInt или каким-то похожим образом. Наличие такого типа очень важно для научных вычислений.
Приведем пример, как наш JSON-документ можно распарсить, например, на Go с использованием специального типа:
package main import ( "encoding/json" "fmt" "math/big" ) func main() < var object struct < Foo big.Int `json:"foo"` >b := []byte(`< "foo": 123456789123456789123 >`) if err := json.Unmarshal(b, &object); err != nil < panic(err) >fmt.Println(object.Foo.String()) // Outputs: 123456789123456789123 >
Благодаря использованию типа big.Int вышеприведенный код отлично распарсит наше число без потери точности. Как правило, любой другой язык программирования также позволяет добиться аналогичного результата похожим образом.
Попробуем повторить это на JavaScript?
Обратим внимание на параметры JSON.parse. Вторым аргументом метода является специальная callback-функция называемая «reviver» (восстановитель). По-сути это функция десериализации, которая вызывается для каждого значения (value) из распарсиваемого JSON-документа и позволяет менять значение на усмотрение пользователя. Также, в JavaScript есть специальный тип BigInt, позволяющий работать с большими целыми числами.
Супер! Давайте теперь объединим это всё вместе:
const object = JSON.parse( '< "foo": 123456789123456789123 >', (key, value) => (key === 'foo') ? BigInt(value) : value ); console.log(object.foo); // Outputs: 123456789123456794624n
В реализации выше мы проверяем, что ключ соответствует значению: «foo«, и конвертируем значение из JSON-документа в BigInt.
Но подождите! Полученный результат: 123456789123456794624n снова отличается от ожидаемого нами: 123456789123456789123 . В чем дело на этот раз?
Немного копнув глубже, оказывается, что в далеком 2009-ом году разработчики стандарта EcmaScript (JavaScript) проделали не самую хорошую работу. Дело в том, что значение (value), которое передается в пользовательскую функцию (reviver) уже является предварительно десериализованным. Фактически, это приводит к выполнению примерно следующего кода:
(key === 'foo') ? BigInt(123456789123456800000) : 123456789123456800000
Другими словами, как бы Вы того не хотели, не существует способа корректно распарсить это число используя нативный JSON-парсер на JavaScript.
Конечно, в защиту создателей EcmaScript можно сказать, что в то время типа BigInt не существовало и в помине, но, тем не менее, сейчас нам от этого не легче.
Извиняюсь, что перебил!
Недавно я запустил свой Telegram-канал по разработке на JavaScript, там я планирую делиться опытом, новостями и наработанными практиками из мира JS. Заходите не стесняйтесь 🙂
Но есть и хорошие новости!

Комитет TC39 (группа экспертов отвечающих за разработку современного стандарта EcmaScript) рассматривает предложение об улучшении языка (JSON.parse source text access proposal), которое добавляет возможность доступа к исходному тексту JSON-значения в reviver-функцию. Данный стандарт находится уже на третьей стадии (Stage 3) и даже реализован в движке V8 (на котором работает Chromium и Node.js). Достаточно включить флаг: harmony_json_parse_with_source.
Реализация этого функционала в V8 появилась относительно недавно: 10-го Декабря 2022 года, однако само предложение толком не двигается вперед уже более двух лет и, кажется, что мейнтейнеры не особо торопятся его финализировать. Конечно, такая вещь как изменение стандарта требует времени. Думаю пройдет еще не один год, прежде чем данный функционал будет полностью реализован и внедрен во все JS-движки.
Почему это важно?
Нынче я работаю с технологиями Web 3.0 и в этой сфере очень часто можно встретить не просто большие, но огромные числа. Возьмем к примеру Ethereum. Один эфир (Ether) в этой системе равен 1,000,000,000,000,000,000 WEI ( 1E18 ), согласитесь квинтиллион — это довольно большое число. В системах, которые работают с финансами принято хранить денежные значения как целое число условных «центов» (WEI в данном примере), а затем просто округлять такие значения при отображении пользователю. Это позволяет добиться максимальной точности при всех вычислениях.
В то же время формат JSON используется, наверное, в 99% различных API и нам нужен способ передавать такие большие числа между системами. Многие API представляют большие числа не как числа, а как строки, содержащие числа. Отчасти это решает проблему на стороне JS, но это достаточно коряво и нарушает семантику стандарта JSON. Должен быть способ лучше!
Способ лучше

Приняв все вышеизложенное, я решил разработать собственный JSON-парсер на JavaScript, который бы учел все имеющиеся проблемы с парсингом JSON на JS в одном готовом решении и мне удалось оформить это как полноценный полифил. Теперь не нужно ждать внедрения стандарта несколько лет перед его использованием. Возможно это даже поможет с внедрением самого стандарта.
Вот пример как можно использовать новый стандарт совместно с полифилом для нашего случая:
import '@ton.js/json-parse-polyfill'; const object = JSON.parse( '< "foo": 123456789123456789123 >', (key, value, context) => ( (key === 'foo' ? BigInt(context.source) : value) ) ); console.log(object.foo); // Outputs: 123456789123456789123n
Как видите достаточно только импортировать полифил и немного поменять reviver-функцию. Наконец-то оно работает!
В завершение
Иногда, чтобы сделать правильную вещь — нужно сделать вещь не очень правильную, в моем случае это было переизобретением колеса в лице собственного JSON-парсера. Но мне хочется верить, что оно того стоит.
Кстати, кроме доступа к исходному тексту JSON-значения из документа, полифил также добавляет доступ к пути из ключей соответствующему каждому конкретному значению, это позволяет существенно упростить парсинг документов и избежать повторного обхода всех значений объекта. В дополнение, парсер имеет фикс безопасности, который применяется, в частности, в Fastify.
Ну, а если Вам нужно еще больше гибкости и удобства при парсинге JSON-документов, то обратите внимание на мою дополнительную библиотеку, которая позволяет матчить значения по их путям используя некое подобие глобов.
Ознакомиться с документацией и примерами всех библиотек можно в репозитории на GitHub. Также не стесняйтесь делиться собственным мнением и задавать вопросы в комментариях.
Удачного парсинга! Теперь ни одно подлое число от Вас не сбежит!
Понравилась статья?
Если статья показалась Вам полезной, пожалуйста, поставьте звезду на GitHub.
Также, приглашаю на мой новый канал по JavaScript-разработке в Telegram. Весь новый контент я выкладываю там.
Вопросы
- Какие есть недостатки при использовании этого полифила?
Сам полифил не очень большой, всего 8 КБ несжатого кода. Однако, нужно понимать, что он будет работать медленнее, чем нативная реализация. В 25 раз медленнее, если быть точным. Но, данный парсер позволяет пропускать через себя 1 МБ вложенных JSON-данных за ~40 миллисекунд. Этого должно быть вполне достаточно для большинства приложений.
Также, полифил использует кастомный парсер только в том случае, когда Вы применяете функционал из нового стандарта (аргумент context в reviver-функции), во всех остальных случаях используется обычная нативная реализация.
- Написать свой парсер не такая простая задача, он точно работает корректно?
Вся прелесть JSON в том, что этот формат имеет очень простую спецификацию. Также, парсер хорошо покрыт unit-тестами и протестирован на большом количестве реальных сложных документов. Код парсера написан на предельно строгом TypeScript, а сгенерированные бандлы проверяются перед каждым релизом как вручную, так и автоматически на предмет безопасности. Также, библиотека имеет ноль зависимостей и включает дополнительные фичи повышающие безопасность. Таким образом, библиотека может быть использована даже в проектах с достаточно высокими требованиями к безопасности.
Подробнее про безопасность в npm и выбор зависимостей Вы можете почитать в моем цикле статей на Хабре.
- Как лучше представлять большие числа в JSON-документах?
Стандарт JSON не накладывает каких-либо ограничений на размер чисел, однако, авторы некоторых API часто представляют большие числа как строки в своих JSON-документах:
Данный подход позволяет JS парсить большие числа используя нативную реализацию.
Однако, я абсолютно убежден, что правильным решением является использование семантически-корректного типа для представления больших чисел в JSON — number. Это не вина стандарта JSON и других платформ в том, что разработчики EcmaScript оказались столь недальновидными. Ровно по этой причине комитет TC39 работает над внедрением нового стандарта, а я разработал описанные выше библиотеки.
P/S: в комментариях поделились интересным кейсом — если Ваш API имеет прослойки между сервером и клиентом, то представление данных стоит внимательно проверять, бывают случаи, когда какой-нибудь API Gateway может «портить» числа в документах.
- JavaScript
- Совершенный код
- Криптовалюты
JSON.parse()
The JSON.parse() static method parses a JSON string, constructing the JavaScript value or object described by the string. An optional reviver function can be provided to perform a transformation on the resulting object before it is returned.
Try it
Syntax
JSON.parse(text) JSON.parse(text, reviver)
Parameters
The string to parse as JSON. See the JSON object for a description of JSON syntax.
If a function, this prescribes how each value originally produced by parsing is transformed before being returned. Non-callable values are ignored. The function is called with the following arguments:
The key associated with the value.
The value produced by parsing.
Return value
The Object , Array , string, number, boolean, or null value corresponding to the given JSON text .
Exceptions
Thrown if the string to parse is not valid JSON.
Description
JSON.parse() parses a JSON string according to the JSON grammar, then evaluates the string as if it’s a JavaScript expression. The only instance where a piece of JSON text represents a different value from the same JavaScript expression is when dealing with the «__proto__» key — see Object literal syntax vs. JSON.
The reviver parameter
If a reviver is specified, the value computed by parsing is transformed before being returned. Specifically, the computed value and all its properties (in a depth-first fashion, beginning with the most nested properties and proceeding to the original value itself) are individually run through the reviver .
The reviver is called with the object containing the property being processed as this (unless you define the reviver as an arrow function, in which case there’s no separate this binding) and two arguments: key and value , representing the property name as a string (even for arrays) and the property value. If the reviver function returns undefined (or returns no value — for example, if execution falls off the end of the function), the property is deleted from the object. Otherwise, the property is redefined to be the return value. If the reviver only transforms some values and not others, be certain to return all untransformed values as-is — otherwise, they will be deleted from the resulting object.
Similar to the replacer parameter of JSON.stringify() , for arrays and objects, reviver will be last called on the root value with an empty string as the key and the root object as the value . For other valid JSON values, reviver works similarly and is called once with an empty string as the key and the value itself as the value .
If you return another value from reviver , that value will completely replace the originally parsed value. This even applies to the root value. For example:
const transformedObj1 = JSON.parse('[1,5,]', (key, value) => return typeof value === "object" ? undefined : value; >); console.log(transformedObj1); // undefined
There is no way to work around this generically. You cannot specially handle the case where key is an empty string, because JSON objects can also contain keys that are empty strings. You need to know very precisely what kind of transformation is needed for each key when implementing the reviver.
Note that reviver is run after the value is parsed. So, for example, numbers in JSON text will have already been converted to JavaScript numbers, and may lose precision in the process. To transfer large numbers without loss of precision, serialize them as strings, and revive them to BigInts, or other appropriate arbitrary precision formats.
Examples
Using JSON.parse()
JSON.parse("<>"); // <> JSON.parse("true"); // true JSON.parse('"foo"'); // "foo" JSON.parse('[1, 5, "false"]'); // [1, 5, "false"] JSON.parse("null"); // null
Using the reviver parameter
JSON.parse( '', (key, value) => typeof value === "number" ? value * 2 // return value * 2 for numbers : value, // return everything else unchanged ); // JSON.parse('>>', (key, value) => console.log(key); return value; >); // 1 // 2 // 4 // 6 // 5 // 3 // ""
Using reviver when paired with the replacer of JSON.stringify()
In order for a value to properly round-trip (that is, it gets deserialized to the same original object), the serialization process must preserve the type information. For example, you can use the replacer parameter of JSON.stringify() for this purpose:
// Maps are normally serialized as objects with no properties. // We can use the replacer to specify the entries to be serialized. const map = new Map([ [1, "one"], [2, "two"], [3, "three"], ]); const jsonText = JSON.stringify(map, (key, value) => value instanceof Map ? Array.from(value.entries()) : value, ); console.log(jsonText); // [[1,"one"],[2,"two"],[3,"three"]] const map2 = JSON.parse(jsonText, (key, value) => Array.isArray(value) ? new Map(value) : value, ); console.log(map2); // Map < 1 =>"one", 2 => "two", 3 => "three" >
Because JSON has no syntax space for annotating type metadata, in order to revive values that are not plain objects, you have to consider one of the following:
- Serialize the entire object to a string and prefix it with a type tag.
- «Guess» based on the structure of the data (for example, an array of two-member arrays)
- If the shape of the payload is fixed, based on the property name (for example, all properties called registry hold Map objects).
JSON.parse() does not allow trailing commas
// both will throw a SyntaxError JSON.parse("[1, 2, 3, 4, ]"); JSON.parse('');
JSON.parse() does not allow single quotes
// will throw a SyntaxError JSON.parse("");
Specifications
| Specification |
|---|
| ECMAScript Language Specification # sec-json.parse |
Browser compatibility
BCD tables only load in the browser
See also
Found a content problem with this page?
- Edit the page on GitHub.
- Report the content issue.
- View the source on GitHub.
This page was last modified on Sep 12, 2023 by MDN contributors.
Your blueprint for a better internet.
MDN
Support
- Product help
- Report an issue
Our communities
Developers
- Web Technologies
- Learn Web Development
- MDN Plus
- Hacks Blog
- Website Privacy Notice
- Cookies
- Legal
- Community Participation Guidelines
Visit Mozilla Corporation’s not-for-profit parent, the Mozilla Foundation.
Portions of this content are ©1998– 2023 by individual mozilla.org contributors. Content available under a Creative Commons license.
How To Use JSON.parse() and JSON.stringify()

The JSON object, available in all modern browsers, has two useful methods to deal with JSON-formatted content: parse and stringify .
JSON.parse()
JSON.parse() takes a JSON string and transforms it into a JavaScript object.
let userStr = ''; let userObj = JSON.parse(userStr); console.log(userObj);
Executing this code will produce the following output:
Output email: "sammy@example.com" name: "Sammy" plan: "Pro"
Trailing commas are not valid in JSON, so JSON.parse() throws an error if the string passed to it has trailing commas.
JSON.parse() can take a function as a second argument that can transform the object values before they are returned.
Here the object’s values are transformed to uppercase in the returned object of the parse method:
let userStr = ''; let userObj = JSON.parse(userStr, (key, value) => if (typeof value === 'string') return value.toUpperCase(); > return value; >); console.log(userObj);
Executing this code will produce the following output:
Output email: "SAMMY@EXAMPLE.COM" name: "SAMMY" plan: "PRO"
The values have been transformed to uppercase characters.
JSON.stringify()
JSON.stringify() takes a JavaScript object and transforms it into a JSON string.
let userObj = name: "Sammy", email: "sammy@example.com", plan: "Pro" >; let userStr = JSON.stringify(userObj); console.log(userStr);
Executing this code will produce the following output:
Output
JSON.stringify() can take two additional arguments. The first one is a replacer function. The second is a String or Number value to use as a space in the returned string.
The replacer function can be used to filter out values, as any value returned as undefined will be out of the returned string:
let userObj = name: "Sammy", email: "sammy@example.com", plan: "Pro" >; function replacer(key, value) console.log(typeof value); if (key === 'email') return undefined; > return value; > let userStrReplacer = JSON.stringify(userObj, replacer); console.log(userStrReplacer);
Executing this code will produce the following output:
Output
The email key-value pair has been removed from the object.
And an example with a space argument passed-in:
let userObj = name: "Sammy", email: "sammy@example.com", plan: "Pro" >; let userStrSpace = JSON.stringify(user, null, '. '); console.log(userStrSpace);
Executing this code will produce the following output:
Output
The indentation has been replaced with . .
Conclusion
In this tutorial, you used the JSON.parse() and JSON.stringify() methods. If you’d like to learn more about working with JSON in Javascript, check out our How To Work with JSON in JavaScript tutorial.
For more information on coding in JavaScript, take a look at our How To Code in JavaScript series, or check out our JavaScript topic page for exercises and programming projects.
Want to deploy your application quickly? Try Cloudways, the #1 managed hosting provider for small-to-medium businesses, agencies, and developers — for free. DigitalOcean and Cloudways together will give you a reliable, scalable, and hassle-free managed hosting experience with anytime support that makes all your hosting worries a thing of the past. Start with $100 in free credits!
