JSON | |
---|---|
Расширение | .json |
MIME-тип | application/json[1] |
Тип формата | Обмен данными |
Расширен из | JavaScript |
Стандарт(ы) | RFC 8259 |
Сайт | json.org (англ.) json.org/json-fr.… (фр.) json.org/json-it.… (итал.) |
Медиафайлы на Викискладе |
JSON (англ. JavaScript Object Notation, обычно произносится как /ˈdʒeɪsən/ JAY-sən [2]) — текстовый формат обмена данными, основанный на JavaScript. Как и многие другие текстовые форматы, JSON легко читается людьми. Формат JSON был разработан Дугласом Крокфордом[3].
Несмотря на происхождение от JavaScript (точнее, от подмножества языка стандарта ECMA-262 1999 года), формат считается независимым от языка и может использоваться практически с любым языком программирования. Для многих языков существует готовый код для создания и обработки данных в формате JSON.
Использование
За счёт своей лаконичности по сравнению с XML, формат JSON может быть более подходящим для сериализации сложных структур.Если говорить о веб-приложениях, в таком ключе он уместен в задачах обмена даннымикак между браузером и сервером (AJAX), так и между самими серверами (программные HTTP-сопряжения).
Поскольку формат JSON является подмножеством синтаксиса языка JavaScript, то он может быть быстро десериализован встроенной функцией eval().Кроме того, возможна вставка вполне работоспособных JavaScript-функций.В языке PHP, начиная с версии 5.2.0, поддержка JSON включена в ядро в виде функций json_decode() и json_encode(), которые сами преобразуют типы данных JSON в соответствующие типы PHP и наоборот.
Синтаксис
JSON-текст представляет собой (в закодированном виде) одну из двух структур:
- Набор пар ключ: значение. В различных языках это реализовано как объект, запись, структура, словарь, хэш-таблица, список с ключом или ассоциативный массив. Ключом может быть только строка (регистрозависимая: имена с буквами в разных регистрах считаются разными[4]), значением — любая форма.
- Упорядоченный набор значений. Во многих языках это реализовано как массив, вектор, список или последовательность.
Это универсальные структуры данных: как правило, любой современный язык программирования поддерживает их в той или иной форме. Они легли в основу JSON, так как он используется для обмена данными между различными языками программирования.
В качестве значений в JSON могут быть использованы:
- Объект — это неупорядоченное множество пар ключ:значение, заключённое в фигурные скобки «{ }». Ключ описывается строкой, между ним и значением стоит символ «:». Пары ключ-значение отделяются друг от друга запятыми.
- Массив (одномерный) — это упорядоченное множество значений. Массив заключается в квадратные скобки «[ ]». Значения разделяются запятыми.
- Число.
- Литералы true, false и null.
- Строка — это упорядоченное множество из нуля или более символов юникода, заключённое в двойные кавычки. Символы могут быть указаны с использованием escape-последовательностей, начинающихся с обратной косой черты «» (поддерживаются варианты ‘, «, , /, t, n, r, f и b), или записаны шестнадцатеричным кодом в кодировке Unicode в виде uFFFF.
Строка очень похожа на одноимённый тип данных в языках С и Java. Число тоже очень похоже на С- или Java-число, за исключением того, что используется только десятичный формат. Пробелы могут быть вставлены между любыми двумя синтаксическими элементами.
Следующий пример показывает JSON-представление объекта, описывающего человека. В объекте есть строковые поля имени и фамилии, объект, описывающий адрес, и массив, содержащий список телефонов. Как видно из примера, значение может представлять собой вложенную структуру.
{ «firstName»: «Иван», «lastName»: «Иванов», «address»: { «streetAddress»: «Московское ш., 101, кв.101», «city»: «Ленинград», «postalCode»: «101101» }, «phoneNumbers»: [ «812 123-1234», «916 123-4567» ]}
Обратите внимание на пару «postalCode»: «101101». В качестве значений в JSON могут быть использованы как число так и строка. Поэтому запись «postalCode»: «101101» содержит строку, а «postalCode»: 101101 — уже числовое значение. Учитывая неопределенность типа переменных в JS (определены только типы значений), в дальнейшем, как правило, не возникает проблем с приведением типа. Но если данные в формате JSON обрабатываются в другой среде, отличной от JS, то нужно быть внимательным.
На языке XML подобная структура выглядела бы примерно так:
<person> <firstName>Иван</firstName> <lastName>Иванов</lastName> <address> <streetAddress>Московское ш., 101, кв.101</streetAddress> <city>Ленинград</city> <postalCode>101101</postalCode> </address> <phoneNumbers> <phoneNumber>812 123-1234</phoneNumber> <phoneNumber>916 123-4567</phoneNumber> </phoneNumbers></person>
или так:
<person firstName=»Иван» lastName=»Иванов»> <address streetAddress=»Московское ш., 101, кв.101″ city=»Ленинград» postalCode=»101101″ /> <phoneNumbers> <phoneNumber>812 123-1234</phoneNumber> <phoneNumber>916 123-4567</phoneNumber> </phoneNumbers></person>
JSON5
JSON5 — предложенное расширение формата json в соответствии с синтаксисом ECMAScript 5, вызванное тем, что json используется не только для общения между программами, но и создаётся/редактируется вручную[5]. JSON5 является корректным кодом ECMAScript 5. Для некоторых языков программирования уже существуют парсеры json5[6].
Некоторые нововведения:
- Поддерживаются как однострочные //, так и многострочные /* */ комментарии.
- Объекты и списки могут иметь запятую после последнего элемента (удобно при копировании элементов).
- Ключи объекта могут быть без кавычек, если они являются валидными идентификаторами ECMAScript 5.
- Строки могут заключаться как в одинарные, так и в двойные кавычки.
- Числа могут быть в шестнадцатеричном виде, начинаться или заканчиваться десятичной точкой, включать Infinity, -Infinity, NaN и -NaN, начинаться со знака +.
Сравнение с YAML
Как функционально, так и синтаксически JSON является подмножеством языка YAML. В частности, спецификация YAML 1.2 указывает, что «любой файл в формате JSON является корректным файлом в формате YAML»[7]. Наиболее распространённый парсер YAML способен обрабатывать и JSON[8]. Спецификация YAML до версии 1.2 не полностью покрывала JSON, в первую очередь из-за отсутствия родной поддержки UTF-32 в YAML, а также требования пробела после разделителя-запятой; кроме того, спецификация JSON включала комментарии в стиле /* */.
Наиболее важным отличием YAML является набор расширений синтаксиса, которым нет аналогов в JSON:
- поддержка реляционных данных: в YAML-документе можно ссылаться на якорь, встретившийся ранее в файле/потоке; таким образом можно выразить рекурсивные структуры.
- поддержка расширяемых типов данных помимо примитивов: строк, чисел, логических значений и т. д.
- поддержка блочного синтаксиса с отступами; он позволяет описать структурированные данные без использования лишних символов: всевозможных скобок, кавычек и т. д.
JSON Schema
JSON Schema — один из языков описания структуры JSON-документа. Использует синтаксис JSON. Базируется на концепциях XML Schema, RelaxNG, Kwalify. JSON Schema — самоописательный язык: при его использовании для обработки данных и описания их допустимости могут использоваться одни и те же инструменты сериализации/десериализации[9].
Формат JSON-LD для связанных данных
Основная статья: JSON-LD
Стандарт JSON не поддерживает ссылки на объекты, но желаемого результата можно достичь при помощи дополнительных соглашений. Рекомендацией W3C для связанных данных является JSON-LD, в котором использована модель данных RDF. В JSON-LD к данным добавляется контекст (context), связывающий свойства объектов JSON-документа с элементами онтологий[10].
Использование JSON в Ajax
Следующий пример Javascript-кода показывает, как браузер может использовать XMLHttpRequest, чтобы запрашивать с сервера объект в формате JSON (серверная часть программы опущена; в ней должен быть размещён код, отправляющий данные в формате JSON-строки в ответ на запросы по url).
var http_request = new XMLHttpRequest();http_request.onreadystatechange = function () { if(http_request.readyState !== 4) return; if(http_request.status !== 200 ) throw new Error(‘request was defeated’) do_something_with_object(JSON.parse(http_request.responseText)); http_request = null;};http_request.open( «GET», url, true );http_request.send(null);
Заметим, что данный пример применения XMLHttpRequest не поддерживает Internet Explorer до версии 6 включительно, так что для них следует использовать несколько иной код. Возможности применения XMLHttpRequest ограничены из-за правила ограничения домена (same origin policy): URL ответ на запрос должен находиться в том же DNS домене, что и сервер, на котором находится страница, запрашивающая ответ. В качестве альтернативы применяется подход JSONP, включающий в себя использование закодированного вызова функции, передающегося между клиентом и сервером, чтобы клиент мог загружать закодированные в JSON данные со сторонних доменов, и уведомлять о завершении вызывающую сторону, хотя это приводит к некоторым рискам для безопасности и дополнительным требованиям к серверу.
Как вариант, в коде страницы можно использовать элементы <iframe> для асинхронного запроса JSON данных, или просто <form action=»url_to_cgi_script»> . Эти подходы были распространены до появления широкой поддержки XMLHttpRequest.
Также можно использовать для передачи JSON-данных динамические теги <script>. С помощью этого метода можно обойти правило ограничения домена (same origin policy), но он приводит к появлению уязвимого кода. В качестве более безопасной альтернативы было предложено использовать JSONRequest.
Вопросы безопасности
Хотя JSON предназначен для передачи данных в сериализованном виде, его синтаксис соответствует синтаксису JavaScript и это создаёт ряд проблем безопасности. Зачастую для обработки данных, полученных от внешнего источника в формате JSON, к ним применяется функция eval() без какой-либо предварительной проверки.
JavaScript eval()
Поскольку JSON представляется синтаксически правильным фрагментом кода JavaScript, простейшим способом разбора JSON-данных в JavaScript-программе является использование встроенной в JavaScript функции eval(), которая предназначена для выполнения JavaScript-выражений. При этом подходе отпадает необходимость в использовании дополнительных парсеров.
Техника использования eval() делает систему уязвимой, если источник используемых JSON-данных не является доверенным (англ.). В качестве таких данных может выступать вредоносный JavaScript код для атак класса Внедрение кода (англ.). С помощью данной уязвимости возможно осуществлять кражу данных, подделку аутентификации. Тем не менее, уязвимость можно устранить за счёт использования дополнительных средств проверки данных на корректность. Например, до выполнения eval() полученные от внешнего источника данные могут проверяться с помощью регулярных выражений. В RFC, определяющей JSON[11], предлагается использовать следующий код для проверки его соответствия формату JSON
var my_JSON_object = !(/[^,:{}[]0-9.-+Eaeflnr-u nrt]/.test(text.replace(/»(.|[^»])*»/g, »))) &&eval(‘(‘ + text + ‘)’);
Как более безопасная альтернатива eval() была предложена новая функция JSON.parse(), способная обрабатывать только JSON-данные. Она была представлена в четвёртой версии стандарта ECMAScript и описана в статье «JSON: Обезжиренная альтернатива XML»[12]. В настоящее время она доступна как библиотека JavaScript[13] и была включена в пятую редакцию ECMAScript.
Встроенный JSON
Последние версии веб-браузеров имеют встроенную поддержку JSON и способны его обрабатывать без вызова функции eval(), приводящей к вышеописанной проблеме с безопасностью. Обработка JSON в таком случае обычно осуществляется быстрее. Так в июне 2009 года следующие браузеры имели встроенную поддержку JSON:
- Mozilla Firefox 3.5+[14]
- Microsoft Internet Explorer 8[15]
- Opera 10.5+[16]
- Браузеры, основанные на WebKit (например, Google Chrome и Apple Safari)[17]
По крайней мере, пять популярных библиотек JavaScript используют встроенный JSON, в случае его доступности:
Подделка кроссдоменного запроса
В этом разделе не хватает ссылок на источники информации.Информация должна быть проверяема, иначе она может быть поставлена под сомнение и удалена. Вы можете отредактировать эту статью, добавив ссылки на авторитетные источники. Эта отметка установлена 22 мая 2018 года. |
Непродуманное использование JSON делает сайты уязвимыми к подделке межсайтовых запросов (CSRF или XSRF)[24]. Поскольку тег <script> допускает использование источника, не принадлежащего к тому же домену, что и использующий ресурс, это позволяет выполнять код под видом данных, представленных в формате JSON, в контексте произвольной страницы, что делает возможным компрометацию паролей или другой конфиденциальной информации пользователей, прошедших авторизацию на другом сайте.
Это представляется проблемой только в случае содержания в JSON-данных конфиденциальной информации, которая может быть компрометирована третьей стороной и если сервер рассчитывает на политику одного источника (англ.), блокируя доступ к данным при обнаружении внешнего запроса. Это не является проблемой, если сервер определяет допустимость запроса, предоставляя данные только в случае его корректности. HTTP cookie нельзя использовать для определения этого. Исключительное использование HTTP cookie используется подделкой межсайтовых запросов.
JSONP и JSONPP
JSONP (англ. JSON Padding — «JSON с подкладкой») является расширением JSON, когда имя функции обратного вызова указывается в качестве входного аргумента.
В основу технологии положен тот факт, что политика безопасности браузера не запрещает использовать тег <script type=»text/javascript» src=»…»></script> для обращения к серверам, отличным от сервера, с которого произошла загрузка страницы.
Без использования технологии JSONP (то есть используя просто JSON кодирование данных) сервер может вернуть только данные. Например, так:
{«paper»: «A4», «count»: 5}
Однако это только данные, и они не могут влиять на браузер.
Используя технику JSONP, стороннему серверу передаётся в строке вызова (GET) имя callback функции:
<script type=»text/javascript» src=»http://example.com/getjson?jsonp=parseResponse»></script>
Здесь параметр jsonp содержит имя callback функции parseResponse.
Теперь посторонний сервер example.com может вернуть следующий код:
parseResponse({«paper»: «A4», «count»: 5})
Теперь код вызывает javascript-функцию первого домена.
Первоначально идея была предложена в блоге MacPython в 2005 году[25] и в настоящее время используется многими Web 2.0 приложениями, такими, как Dojo Toolkit Applications, Google Toolkit Applications [1] и zanox Web Services. Дальнейшие расширения этого протокола были предложены с учётом ввода дополнительных аргументов, как, например, в случае JSONPP[26] при поддержке S3DB веб-сервисов.
Поскольку JSONP использует скрипт теги, вызовы по сути открыты миру. По этой причине JSONP может быть неуместными для хранения конфиденциальных данных[27].
Включение скриптовых тегов от удалённых сайтов позволяет им передать любой контент на сайте. Если удалённый сайт имеет уязвимости, которые позволяют выполнить Javascript инъекции, то исходный сайт также может быть затронут ими.
JSONPP (англ. parameterized JSON with padding — «параметризованный JSON с подкладкой») — развитие идеи JSONP.
JSONPP включает в себя URL источника, имя функции, которая будет обрабатывать JSON данные, строка для eval после получения данных и строка для eval после окончания обработки данных:
JSON_call(SRC,JSONP,JSONPP,ONLOAD);
в итоге оборачивается
ans = JSONP(SRC){ eval(JSONPP(ans)); eval(ONLOAD);}
Вообще, для самой идеи JSONPP не принципиально количество параметров. Достаточно SRC, JSONP, JSONPP (и их обработка на стороне сервера, а затем клиента) для того, чтобы это был JSONPP.
Рассмотрим на примере работы с сервисом S3DB.
function s3db_jsonpp_call(src, next_eval){var call = «call_»+Math.random().toString().replace(/./g,»»);var headID = document.getElementsByTagName(«head»)[0];var script = document.createElement(‘script’);script.id = call;script.type = ‘text/javascript’;// using padded, parameterized jsonsrc = src+»&format=json&jsonp=s3db_jsonpp&jsonpp=»+next_eval+»&onload=remove_element_by_id(‘»+script.id+»‘)»;script.src = src;headID.appendChild(script); // retrieve answer}function s3db_jsonpp(ans, jsonpp){eval(jsonpp);return ans;}function remove_element_by_id(id){var e = document.getElementById(id);e.parentNode.removeChild(e);return false;}
В примере функция s3db_jsonpp_call() создаёт в DOM в части head элемент script, src которого соответствует вызову JSONPP.
После получения ответа от сервера будет вызвана s3db_jsonpp() — она передана в параметрах вызова, как это должно быть по правилам JSONP.
Внутри s3db_jsonpp() сработает eval(jsonpp), и произойдёт возврат значения ans.
Вызов eval(onload) приводит к выполнению remove_element_by_id() с id созданного скрипта в head и в итоге к его удалению, ведь он уже всё равно не будет использоваться, поскольку id в примере было сгенерировано случайным образом в самом начале функции s3db_jsonpp_call(). Этот вызов в ответе сервера.
JSONB
Бинарное расширение JSON, внедрённое в СУБД PostgreSQL в версии 9.4.18.Фактически, JSONB является бинарным представлением JSON[28], с тем различием, что в хранимых строках пробелы удаляются, сортировка объектов не сохраняется и сохраняется только последнее значение для ключей-дубликатов[29].
См. также
Примечания
- ↑ Crockford D. The application/json Media Type for JavaScript Object Notation (JSON) (англ.) — Internet Engineering Task Force, 2006. — 10 p. — doi:10.17487/RFC4627
- ↑ Doug Crockford «Google Tech Talks: JavaScript: The Good Parts» (неопр.) (7 February 2009).
- ↑ JSON Redux AKA RFC7159 (неопр.).
- ↑ http://jsonrpc.org/historical/json-rpc-1-1-alt.html#service-procedure-and-parameter-names
- ↑ JSON5 by aseemk
- ↑ https://github.com/json5/json5/wiki/In-The-Wild
- ↑ YAML Ain’t Markup Language (YAML™) Version 1.2 (англ.) (недоступная ссылка). — Working Draft 2008-05-11. Дата обращения 24 сентября 2009. Архивировано 16 мая 2008 года.
- ↑ YAML is JSON (неопр.). RedHanded (07 апреля 2005). Дата обращения 25 сентября 2012..
- ↑ Json.Com. JSON Schema Proposal (англ.) (недоступная ссылка). Архивировано 14 мая 2008 года.
- ↑ JSON-LD Syntax 1.0 (неопр.) (27 декабря 2011). Дата обращения 30 декабря 2011.
- ↑ RFC 4627 (Request for Comments)
- ↑ JSON: Обезжиренная альтернатива XML (англ.). Архивировано 12 февраля 2012 года.
- ↑ json2.js (англ.). Дата обращения 24 сентября 2009. Архивировано 12 февраля 2012 года.
- ↑ Использование встроенного JSON (англ.).
- ↑ Встроенный JSON в IE8 (англ.). Архивировано 12 февраля 2012 года.
- ↑ Web спецификации, поддерживаемые в Opera Presto 2.5 (англ.) (March 10, 2010). Дата обращения 29 марта 2010. Архивировано 12 февраля 2012 года.
- ↑ Реализация ES 3.1 объекта JSON (англ.).
- ↑ Ticket #4429lang=en (неопр.). Архивировано 12 февраля 2012 года.
- ↑ Ticket #4429 (неопр.) (May 22, 2009). Дата обращения 3 июля 2009. Архивировано 12 февраля 2012 года.
- ↑ Ticket #8111lang=en (неопр.). Архивировано 12 февраля 2012 года.
- ↑ MooTools Core & More 1.3.1 (неопр.). Архивировано 12 февраля 2012 года.
- ↑ YUI 2: JSON utility (неопр.) (September 1, 2009). Дата обращения 22 октября 2009. Архивировано 12 февраля 2012 года.
- ↑ Learn JSON (неопр.) (April 7, 2010). Дата обращения 7 апреля 2010. Архивировано 12 февраля 2012 года.
- ↑ Джереми Гроссмэн. Продвинутые техники атак на веб-приложения, использующие GMail (англ.). WhiteHat Security. Дата обращения 23 сентября 2009. Архивировано 12 февраля 2012 года.
- ↑ from __future__ import * » Remote JSON — JSONP (неопр.). Bob.pythonmac.org. Дата обращения 8 сентября 2008. Архивировано 12 февраля 2012 года.
- ↑ Шаблон:Cite paper
- ↑ RIAspot. JSON P for Cross Site XHR (неопр.) (недоступная ссылка). Архивировано 5 декабря 2008 года.
- ↑ Когда использовать неструктурированные типы данных в PostgreSQL? Сравнение Hstore vs. JSON vs. JSONB (рус.). Дата обращения 4 июля 2018.
- ↑ Чем PostgreSQL лучше других SQL баз данных с открытым исходным кодом. Часть 1 (рус.). Дата обращения 4 июля 2018.
Ссылки
- Официальная домашняя страница формата на русском языке
- json.js, json2.js — библиотека, разработанная Дугласом Крокфордом, для работы с данными JSON в JavaScript. Расширяет объект Object методом toJSONString, который затем присутствует в любом объекте, и осуществляет его преобразование в строку формата JSON.
- json-rpc.org (англ.)
- Глава о JSON из онлайн учебника JavaScript (рус.)
- JSON-форматировщик (англ.)
- JSON-просмотрщик (англ.)
- JSON-валидатор (англ.)