Формат JSON, метод toJSON
Допустим, у нас есть сложный объект, и мы хотели бы преобразовать его в строку, чтобы отправить по сети или просто вывести для логирования.
Естественно, такая строка должна включать в себя все важные свойства.
Мы могли бы реализовать преобразование следующим образом:
…Но в процессе разработки добавляются новые свойства, старые свойства переименовываются и удаляются. Обновление такого toString каждый раз может стать проблемой. Мы могли бы попытаться перебрать свойства в нём, но что, если объект сложный, и в его свойствах имеются вложенные объекты? Мы должны были бы осуществить их преобразование тоже.
К счастью, нет необходимости писать код для обработки всего этого. У задачи есть простое решение.
JSON.stringify
JSON (JavaScript Object Notation) – это общий формат для представления значений и объектов. Его описание задокументировано в стандарте RFC 4627. Первоначально он был создан для JavaScript, но многие другие языки также имеют библиотеки, которые могут работать с ним. Таким образом, JSON легко использовать для обмена данными, когда клиент использует JavaScript, а сервер написан на Ruby/PHP/Java или любом другом языке.
JavaScript предоставляет методы:
- JSON.stringify для преобразования объектов в JSON.
- JSON.parse для преобразования JSON обратно в объект.
Например, здесь мы преобразуем через JSON.stringify данные студента:
Метод JSON.stringify(student) берёт объект и преобразует его в строку.
Полученная строка json называется JSON-форматированным или сериализованным объектом. Мы можем отправить его по сети или поместить в обычное хранилище данных.
Обратите внимание, что объект в формате JSON имеет несколько важных отличий от объектного литерала:
- Строки используют двойные кавычки. Никаких одинарных кавычек или обратных кавычек в JSON. Так ‘John’ становится "John" .
- Имена свойств объекта также заключаются в двойные кавычки. Это обязательно. Так age:30 становится "age":30 .
JSON.stringify может быть применён и к примитивам.
JSON поддерживает следующие типы данных:
- Объекты
- Массивы [ . ]
- Примитивы:
- строки,
- числа,
- логические значения true/false ,
- null .
JSON является независимой от языка спецификацией для данных, поэтому JSON.stringify пропускает некоторые специфические свойства объектов JavaScript.
- Свойства-функции (методы).
- Символьные ключи и значения.
- Свойства, содержащие undefined .
Обычно это нормально. Если это не то, чего мы хотим, то скоро мы увидим, как можно настроить этот процесс.
Самое замечательное, что вложенные объекты поддерживаются и конвертируются автоматически.
Важное ограничение: не должно быть циклических ссылок.
Здесь преобразование завершается неудачно из-за циклической ссылки: room.occupiedBy ссылается на meetup , и meetup.place ссылается на room :
Исключаем и преобразуем: replacer
Полный синтаксис JSON.stringify :
В большинстве случаев JSON.stringify используется только с первым аргументом. Но если нам нужно настроить процесс замены, например, отфильтровать циклические ссылки, то можно использовать второй аргумент JSON.stringify .
Если мы передадим ему массив свойств, будут закодированы только эти свойства.
Здесь мы, наверное, слишком строги. Список свойств применяется ко всей структуре объекта. Так что внутри participants – пустые объекты, потому что name нет в списке.
Давайте включим в список все свойства, кроме room.occupiedBy , из-за которого появляется цикличная ссылка:
Теперь всё, кроме occupiedBy , сериализовано. Но список свойств довольно длинный.
К счастью, в качестве replacer мы можем использовать функцию, а не массив.
Функция будет вызываться для каждой пары (key, value) , и она должна возвращать заменённое значение, которое будет использоваться вместо исходного. Или undefined , чтобы пропустить значение.
В нашем случае мы можем вернуть value «как есть» для всего, кроме occupiedBy . Чтобы игнорировать occupiedBy , код ниже возвращает undefined :
Обратите внимание, что функция replacer получает каждую пару ключ/значение, включая вложенные объекты и элементы массива. И она применяется рекурсивно. Значение this внутри replacer – это объект, который содержит текущее свойство.
Первый вызов – особенный. Ему передаётся специальный «объект-обёртка»: <"": meetup>. Другими словами, первая (key, value) пара имеет пустой ключ, а значением является целевой объект в общем. Вот почему первая строка из примера выше будет ":[object Object]" .
Идея состоит в том, чтобы дать как можно больше возможностей replacer – у него есть возможность проанализировать и заменить/пропустить даже весь объект целиком, если это необходимо.
Форматирование: space
Третий аргумент в JSON.stringify(value, replacer, space) – это количество пробелов, используемых для удобного форматирования.
Ранее все JSON-форматированные объекты не имели отступов и лишних пробелов. Это нормально, если мы хотим отправить объект по сети. Аргумент space используется исключительно для вывода в удобочитаемом виде.
Ниже space = 2 указывает JavaScript отображать вложенные объекты в несколько строк с отступом в 2 пробела внутри объекта:
Третьим аргументом также может быть строка. В этом случае строка будет использоваться для отступа вместо ряда пробелов.
Параметр space применяется исключительно для логирования и красивого вывода.
Пользовательский «toJSON»
Как и toString для преобразования строк, объект может предоставлять метод toJSON для преобразования в JSON. JSON.stringify автоматически вызывает его, если он есть.
Как видим, date (1) стал строкой. Это потому, что все объекты типа Date имеют встроенный метод toJSON , который возвращает такую строку.
Теперь давайте добавим собственную реализацию метода toJSON в наш объект room (2) :
Как работать с json в javascript
JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write and easy for machines to parse and generate. It is important to realize that, in JavaScript, JSON is a string and not an object.
A basic overview can be found on the json.org
(opens new window) website which also contains links to implementations of the standard in many different programming languages.
# Parsing with a reviver function
A reviver function can be used to filter or transform the value being parsed.
This produces the following result:
This is particularly useful when data must be sent that needs to be serialized/encoded when being transmitted with JSON, but one wants to access it deserialized/decoded. In the following example, a date was encoded to its ISO 8601 representation. We use the reviver function to parse this in a JavaScript Date .
It is important to make sure the reviver function returns a useful value at the end of each iteration. If the reviver function returns undefined , no value or the execution falls off towards the end of the function, the property is deleted from the object. Otherwise, the property is redefined to be the return value.
# Serializing a value
A JavaScript value can be converted to a JSON string using the JSON.stringify function.
- value The value to convert to a JSON string.
- replacer A function that alters the behaviour of the stringification process or an array of String and Number objects that serve as a whitelist for filtering the properties of the value object to be included in the JSON string. If this value is null or is not provided, all properties of the object are included in the resulting JSON string.
- space For readability, the number of spaces used for indentation may be specified as the third parameter.
Alternatively, a string value can be provided to use for indentation. For example, passing ‘\t’ will cause the tab character to be used for indentation.
# Serializing and restoring class instances
You can use a custom toJSON method and reviver function to transmit instances of your own class in JSON. If an object has a toJSON method, its result will be serialized instead of the object itself.
This produces the a string with the following content:
This produces the following object:
# JSON versus JavaScript literals
JSON stands for "JavaScript Object Notation", but it’s not JavaScript. Think of it as just a data serialization format that happens to be directly usable as a JavaScript literal. However, it is not advisable to directly run (i.e. through eval() ) JSON that is fetched from an external source. Functionally, JSON isn’t very different from XML or YAML – some confusion can be avoided if JSON is just imagined as some serialization format that looks very much like JavaScript.
Even though the name implies just objects, and even though the majority of use cases through some kind of API always happen to be objects and arrays, JSON is not for just objects or arrays. The following primitive types are supported:
- String (e.g. "Hello World!" )
- Number (e.g. 42 )
- Boolean (e.g. true )
- The value null
undefined is not supported in the sense that an undefined property will be omitted from JSON upon serialization. Therefore, there is no way to deserialize JSON and end up with a property whose value is undefined .
The string "42" is valid JSON. JSON doesn’t always have to have an outer envelope of "<. >" or "[. ]" .
While nome JSON is also valid JavaScript and some JavaScript is also valid JSON, there are some subtle differences between both languages and neither language is a subset of the other.
Take the following JSON string as an example:
This can be directly inserted into JavaScript. It will be syntactically valid and will yield the correct value:
However, we know that "color" is a valid identifier name and the quotes around the property name can be omitted:
We also know that we can use single quotes instead of double quotes:
But, if we were to take both of these literals and treat them as JSON, neither will be syntactically valid JSON:
JSON strictly requires all property names to be double quoted and string values to be double quoted as well.
It’s common for JSON-newcomers to attempt to use code excerpts with JavaScript literals as JSON, and scratch their heads about the syntax errors they are getting from the JSON parser.
More confusion starts arising when incorrect terminology is applied in code or in conversation.
A common anti-pattern is to name variables that hold non-JSON values as "json":
In the above example, response.data is a JSON string that is returned by some API. JSON stops at the HTTP response domain. The variable with the "json" misnomer holds just a JavaScript value (could be an object, an array, or even a simple number!)
A less confusing way to write the above is:
Developers also tend to throw the phrase "JSON object" around a lot. This also leads to confusion. Because as mentioned above, a JSON string doesn’t have to hold an object as a value. "JSON string" is a better term. Just like "XML string" or "YAML string". You get a string, you parse it, and you end up with a value.
# Serializing with a replacer function
A replacer function can be used to filter or transform values being serialized.
This produces the following string:
# Parsing a simple JSON string
The JSON.parse() method parses a string as JSON and returns a JavaScript primitive, array or object:
# Cyclic object values
Not all objects can be converted to a JSON string. When an object has cyclic self-references, the conversion will fail.
This is typically the case for hierarchical data structures where parent and child both reference each other:
As soon as the process detects a cycle, the exception is raised. If there were no cycle detection, the string would be infinitely long.
# Syntax
- JSON.parse(input[, reviver])
- JSON.stringify(value[, replacer[, space]])
# Parameters
Parameter Details JSON.parse Parse a JSON string input(string) JSON string to be parsed. reviver(function) Prescribes a transformation for the input JSON string. JSON.stringify Serialize a serializable value value(string) Value to be serialized according to the JSON specification. replacer(function or String[] or Number[]) Selectively includes certain properties of the value object. space(String or Number ) If a number is provided, then space number of whitespaces will be inserted of readability. If a string is provided, the string (first 10 characters) will be used as whitespaces. # Remarks
The JSON utility methods were first standardized in ECMAScript 5.1 §15.12
The format was formally defined in The application/json Media Type for JSON (RFC 4627 July 2006) which was later updated in The JSON Data Interchange Format (RFC 7158 March 2013, ECMA-404
(opens new window) October 2013 and RFC 7159 March 2014).
To make these methods available in old browsers such as Internet Explorer 8, use Douglas Crockford’s json2.js
Name already in use
javascript-tutorial-ru / 1-js / 7-js-misc / 2-json / article.md
- Go to file T
- Go to line L
- Copy path
- Copy permalink
- Open with Desktop
- View raw
- Copy raw contents Copy raw contents
Copy raw contents
Copy raw contents
Формат JSON, метод toJSON
В этой главе мы рассмотрим работу с форматом JSON, который используется для представления объектов в виде строки.
Это один из наиболее удобных форматов данных при взаимодействии с JavaScript. Если нужно с сервера взять объект с данными и передать его клиенту, то в качестве промежуточного формата — для передачи по сети, почти всегда используют именно его.
В современных браузерах есть замечательные методы, знание тонкостей которых делает операции с JSON простыми и комфортными.
Данные в формате JSON (RFC 4627) представляют собой:
- JavaScript-объекты < . >или
- Массивы [ . ] или
- Значения одного из типов:
- строки в двойных кавычках,
- число,
- логическое значение true / false ,
- null .
Почти все языки программирования имеют библиотеки для преобразования объектов в формат JSON.
Основные методы для работы с JSON в JavaScript — это:
- JSON.parse — читает объекты из строки в формате JSON.
- JSON.stringify — превращает объекты в строку в формате JSON, используется, когда нужно из JavaScript передать данные по сети.
Вызов JSON.parse(str) превратит строку с данными в формате JSON в JavaScript-объект/массив/значение.
Данные могут быть сколь угодно сложными, объекты и массивы могут включать в себя другие объекты и массивы. Главное, чтобы они соответствовали формату.
Умный разбор: JSON.parse(str, reviver)
Метод JSON.parse поддерживает и более сложные алгоритмы разбора.
Например, мы получили с сервера объект с данными события event .
Он выглядит так:
. И теперь нужно восстановить его, то есть превратить в JavaScript-объект.
Попробуем вызвать для этого JSON.parse :
Дело в том, что значением event.date является строка, а отнюдь не объект Date . Откуда методу JSON.parse знать, что нужно превратить строку именно в дату?
Для интеллектуального восстановления из строки у JSON.parse(str, reviver) есть второй параметр reviver , который является функцией function(key, value) .
Если она указана, то в процессе чтения объекта из строки JSON.parse передаёт ей по очереди все создаваемые пары ключ-значение и может возвратить либо преобразованное значение, либо undefined , если его нужно пропустить.
В данном случае мы можем создать правило, что ключ date всегда означает дату:
Кстати, эта возможность работает и для вложенных объектов тоже:
Сериализация, метод JSON.stringify
Метод JSON.stringify(value, replacer, space) преобразует («сериализует») значение в JSON-строку.
При сериализации объекта вызывается его метод toJSON .
Если такого метода нет — перечисляются его свойства, кроме функций.
Посмотрим это в примере посложнее:
Обратим внимание на два момента:
Дата превратилась в строку. Это не случайно: у всех дат есть встроенный метод toJSON . Его результат в данном случае — строка в таймзоне UTC.
У объекта room нет метода toJSON . Поэтому он сериализуется перечислением свойств.
Мы, конечно, могли бы добавить такой метод, тогда в итог попал бы его результат:
Попытаемся преобразовать в JSON объект, содержащий ссылку на DOM.
Произошла ошибка! В чём же дело? Неужели некоторые объекты запрещены? Как видно из текста ошибки — дело совсем в другом. Глобальный объект window — сложная структура с кучей встроенных свойств и круговыми ссылками, поэтому его преобразовать невозможно. Да и нужно ли?
Во втором параметре JSON.stringify(value, replacer) можно указать массив свойств, которые подлежат сериализации.
Для более сложных ситуаций вторым параметром можно передать функцию function(key, value) , которая возвращает сериализованное value либо undefined , если его не нужно включать в результат:
В примере выше функция пропустит свойство с названием window . Для остальных она просто возвращает значение, передавая его стандартному алгоритму. А могла бы и как-то обработать.
«`smart header То есть, если объект содержит вложенные объекты, массивы и т.п., то все они пройдут через `replacer`.
Использование JSON в JavaScript
JSON (JavaScript Object Notation) – это формат передачи данных. Из названия видно, что формат основан на языке программирования JavaScript, однако он доступен и в других языках (Python, Ruby, PHP, Java).
Читайте также: Основы работы с JSON
В программах JavaScript формат JSON обычно используется в следующих случаях:
- Хранение данных.
- Генерирование структур данных из пользовательского ввода.
- Обмен данными между сервером и клиентом.
- Настройка и проверка данных.
Это руководство познакомит вас с основами использования формата JSON в JavaScript.
Примечание: Руководство предполагает, что вы имеете базовые навыки работы с JavaScript.
Формат JSON
JSON основан на синтаксисе объектов JavaScript. Данные записываются в виде пар «ключ-значение» и помещаются в фигурные скобки.
При работе с JSON все объекты хранятся в файле .json, но также они могут существовать как отдельные объекты в контексте программы.
Читайте также: Основы работы с JSON
Файл .json выглядит так:
<
«first_name» : «John»,
«last_name» : «Smith»,
«online» : true
>Объект JSON в файлах .js или .html выглядит так:
var john = <
«first_name» : «John»,
«last_name» : «Smith»,
«online» : true
>Иногда JSON записывается в виде строки в контексте файла или сценария программы JavaScript.
Преобразование объекта JSON в строку используется для быстрой передачи данных.
Объекты JSON и JavaScript
Формат JSON разрабатывался для использования во всех языках программирования, а объекты JavaScript могут работать только в JavaScript.
Объекты JavaScript и JSON имеют похожий синтаксис. Однако в JavaScript ключи не представлены строками в кавычках. Также значения объектов JavaScript менее ограничены, чем в JSON, и могут выражаться функциями.
Объект JavaScript выглядит так:
var user = <
first_name: «John»,
last_name : «Smith»,
online : true,
full_name : function() <
return this.first_name + » » + this.last_name;
>
>;Как видите, в этом объекте не используются кавычки в ключах (first_name, last_name, online, full_name). Также в нём есть функция (последняя строка).
Чтобы получить доступ к данным JavaScript, нужно вызвать user.first_name с помощью точечной нотации. Это вернёт строку. Чтобы получить полное имя, нужно вызвать функцию user.full_name().
Объекты JavaScript существуют только в пределах языка JavaScript. Если ваши данные должны быть доступны и для других языков программирования, лучше использовать JSON.
Доступ к данным JSON
Данные JSON доступны в Javascript посредством точечной нотации. Чтобы понять, как это работает, рассмотрим такой пример объекта JSON:
var john = <
«first_name» : «John»,
«last_name» : «Smith»,
«online» : true
>Чтобы получить доступ к значениям, нужно использовать точечную нотацию:
john.first_name
john.last_name
john.onlineПеременная john указывается в начале, затем идёт точка и ключ, значение которого нужно извлечь.
Чтобы создать всплывающее предупреждение JavaScript, которое будет извлекать значение ключа first_name, используйте функцию alert():
Также для доступа к данным можно использовать квадратные скобки. При этом ключ нужно взять в кавычки. Попробуйте использовать это в функции alert():
При работе с вложенными массивами нужно вызывать элемент массива по номеру. Предположим, у нас есть такой массив:
var user_profile = <
«username» : «JohnSmith»,
«social_media» : [
<
«description» : «twitter»,
«link» : «https://twitter.com/johnsmith»
>,
<
«description» : «facebook»,
«link» : «https://www.facebook.com/JohnSmith»
>,
<
«description» : «github»,
«link» : «https://github.com/johnsmith»
>
] >Чтобы отобразить строку, которая содержит ссылку на facebook, нужно вызвать элемент массива в контексте точечной нотации:
Обратите внимание: для каждого вложенного элемента используется дополнительная точка.
Функции в JSON
При работе с JSON очень полезно иметь возможность быстро преобразовать строку в объект и наоборот. В этом разделе мы рассмотрим два метода JSON.
Функция JSON.stringify()
Функция JSON.stringify() преобразовывает объекты JSON в строки.
Строки позволяют упростить обмен данными между сервером и клиентом. К примеру, вы можете собирать настройки пользователей на стороне клиента, а затем передавать их на сервер. После этого вы сможете преобразовать строку в объект с помощью метода JSON.parse().
Рассмотрим объект, присвоенный переменной obj. Попробуйте преобразовать его в строку. Для этого нужно передать функции JSON.stringify() переменную obj. Присвойте эту строку переменной s.
Теперь объект стал строкой и является значением переменной s:
Функция JSON.parse()
Строки удобны при обмене данными, но потом их нужно снова преобразовать в объекты. Для этого используется функция JSON.parse().
Примечание: Чтобы преобразовать текст в объект, используйте функцию eval().
Теперь попробуйте преобразовать значение функции s в объект и присвоить его новой переменной:
var o = JSON.parse(s)
Теперь у вас есть объект o, идентичный объекту obj.
Рассмотрим ещё один пример. Функцию JSON.parse() можно использовать в контексте файла HTML:
В HTML-файле JSON-строка s преобразовывается в объект, который извлекается в финальный рендеринг с помощью точечной нотации.
Заключение
JSON обычно используется в JavaScript, однако этот формат широко применяется в других языках программирования.
Больше информации о совместимости и обработке JSON можно найти на сайте проекта.
Сегодня JSON часто используется в API.
Читайте также:
Писать JSON с нуля приходится редко. Обычно данные загружаются из исходников или преобразовываются в JSON. Потому знать, как использовать JSON в программе важнее, чем уметь писать такие файлы.