Содержание


Освоение Ajax

Часть 11. JSON на стороне сервера

Применение JSON на стороне сервера для получения запросов и создания ответов

Comments

Серия контента:

Этот контент является частью # из серии # статей: Освоение Ajax

Следите за выходом новых статей этой серии.

Этот контент является частью серии:Освоение Ajax

Следите за выходом новых статей этой серии.

Настоящая ценность JSON

В предыдущей статье этой серии мы говорили о том, что JSON удобен как формат данных для Ajax-приложений, потому что позволяет быстро конвертировать JavaScript-объекты в строковые значения и наоборот. Так как Ajax-приложения лучше всего приспособлены для отправления и получения обычного текста, то почти всегда предпочтительнее использовать тот API, который умеет его генерировать; JSON же помимо этой возможности позволяет также работать с родными объектами JavaScript и не беспокоиться о том, как эти объекты будут выглядеть в тексте.

XML обладает теми же преимуществами текстового формата, что и JSON, однако API для преобразования JavaScript-объектов в XML (а таковые существуют, и не в единственном числе) не так хорошо проработаны по сравнению с программным интерфейсом JSON; создавая и изменяя объекты, вам иногда самим придётся заботиться о том, чтобы выбранный API смог нормально работать с этими объектами. С JSON всё проще: он обрабатывает практически все мыслимые типы объектов и просто возвращает вам данные в приятном JSON-представлении.

Итак, самая главная ценность JSON состоит в том, что он позволяет работать с JavaScript как с JavaScript, а не как с языком форматирования данных. Так что вы можете применять в своём коде все наработанные навыки по работе с JavaScript-объектами, не заботясь о том, как эти объекты будут преобразованы в текст. Вы лишь вызываете в конце простой JSON-метод:

String myObjectInJSON = myObject.toJSONString();

и получаете текст, который можно отправлять на сервер.

Доставка JSON на сервер

В отправке данных JSON на сервер нет ничего особо сложного, но это важный момент, и у вас есть ряд возможностей для выбора. Однако если вы остановите свой выбор на JSON, то дальнейшие решения принимать будет гораздо проще, так как выбор значительно сузится, и вам не придётся сильно напрягаться по этому поводу. В конце концов, вам просто надо доставить JSON-строку на сервер, причём желательно максимально быстро и просто.

Отправление JSON в парах «имя/значение» методом GET

Самый простой способ доставить JSON-данные на сервер – это преобразовать их в текст и послать его как значение пары «имя/значение». Помните, JSON-отформатированные данные – это всего лишь один довольно большой объект, который выглядит приблизительно так, как показано в листинге 1:

Листинг 1. Простой JavaScript-объект в JSON-формате
var people =  { "programmers": [    { "firstName": "Brett", "lastName":"McLaughlin",
"email": "brett@newInstance.com" },    { "firstName": "Jason", "lastName":"Hunter",
"email": "jason@servlets.com" },    { "firstName": "Elliotte", "lastName":"Harold",
"email": "elharo@macfaq.com" }   ],  "authors": [    { "firstName": "Isaac", 
"lastName": "Asimov", "genre": "science fiction" },    { "firstName": "Tad", 
"lastName": "Williams", "genre": "fantasy" },    { "firstName": "Frank", 
"lastName": "Peretti", "genre": "christian fiction" }   ],  "musicians": [    
{ "firstName": "Eric", "lastName": "Clapton", "instrument": "guitar" },   
{ "firstName": "Sergei", "lastName": "Rachmaninoff", "instrument": "piano" }   ]  }

Итак, этот текст можно отправить серверному скрипту внутри пары «имя/значение», например, так:

var url = "organizePeople.php?people=" + people.toJSONString();
xmlHttp.open("GET", url, true);
xmlHttp.onreadystatechange = updatePage;
xmlHttp.send(null);

Вроде бы всё здесь хорошо, но на самом деле есть одна загвоздка: в нашей JSON-строке с данными присутствуют пробелы и другие символы, которые Web-браузер может попытаться интерпретировать. Чтобы эти символы не вызвали проблем на сервере (и не сорвали бы передачу данных) следует добавить в код JavaScript-функцию escape(). Вот так:

var url = "organizePeople.php?people=" + escape(people.toJSONString());
request.open("GET", url, true);
request.onreadystatechange = updatePage;
request.send(null);

Эта функция обрабатывает пробелы, слеши и всё остальное, что может сбить с толку браузер. Она конвертирует их в «безопасные» в этом смысле символы (например, пробел преобразуется в escape-последовательность %20, которую браузеры уже не воспринимают как пробел, а просто без изменений передают на сервер). Затем уже сервер выполнит обратное преобразование (обычно автоматически), и мы получим строку в том виде, в каком она была до передачи.

У этого подхода есть два недостатка:

  • Во-первых, мы отправляем данные, размер которых потенциально может быть очень большим, посредством GET-запроса, имеющего ограничение на длину URL-строки. Максимально допустимый размер строки очень велик, но мы никогда не знаем, насколько длинную строку получим после преобразования объекта в текст, особенно если этот объект достаточно сложен.
  • Во-вторых, мы отправляем данные через сеть открытым текстом – то есть самым небезопасным из всех мыслимых методов передачи данных.

Для ясности замечу, что оба эти недостатка больше связаны с ограничениями GET-запросов, чем со спецификой JSON. Однако если вы отправляете на сервер больше чем просто фамилию или имя пользователя или результат его выбора в форме на вашем сайте, то эти недостатки могут изрядно подпортить вам жизнь. Если вы начинаете работать с данными, которые могут быть хоть сколько-нибудь конфиденциальными или обладать большим размером, вам определённо следует обратить своё внимание на POST-запросы.

Передача JSON-данных методом POST

Если вы решили использовать для отправки JSON-данных на сервер метод POST вместо GET, то больших изменений в код вносить не придётся. Вот всё, что нужно сделать:

var url = "organizePeople.php?timeStamp=" + new Date().getTime();
request.open("POST", url, true);
request.onreadystatechange = updatePage;
request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
request.send(people.toJSONString());

Большая часть этого кода должна быть вам знакома по статье "Освоение Ajax, часть 3: в которой обсуждалось создание POST-запросов. Здесь мы открываем запрос, используя POST вместо GET, и устанавливаем соответствующий заголовок «Content-Type», указывающий на тип ожидаемых данных. В данном случае он будет выглядеть так: application/x-www-form-urlencoded, давая понять серверу, что мы передаём просто текстовые данные, которые он в принципе мог бы получить и из обычной HTML-формы.

Ещё одним небольшим изменением в коде является добавление к URL текущего времени. Это сделано для того, чтобы предотвратить кэширование запросов и обеспечить их создание и отправку при каждом вызове метода; строки URL каждый раз будут немного различаться благодаря изменению временной метки. Это часто используемый приём, гарантирующий, что POST-запрос будет действительно каждый раз генерироваться заново и Web-браузер не попытается кэшировать ответы от сервера.

JSON – это просто текст

При использовании GET и POST-запросов очень важно, что JSON - это, в конце концов, обычный текст. С ним можно легко работать и передавать серверу, так как он не требует никакого специального кодирования. Текстовые данные можно обработать любым серверным скриптом. Если бы JSON был двоичным форматом или каким-нибудь хитро закодированным текстом, всё было бы не так просто. Итак, JSON – это обычные текстовые данные, которые скрипт в принципе мог бы получить и при подтверждении HTML-формы (как мы видели, когда речь шла о заголовке «Content-Type» в POST-запросах), так что вам не нужно сильно заморачиваться по поводу отправки его на сервер.

Интерпретация JSON на сервере

Как только вы написали свой клиентский JavaScript-код, позволяющий пользователям взаимодействовать с вашими Web-страницами и формами, и получили информацию, которую надо отправить на обработку серверной программе, главным действующим лицом в вашем приложении (и, вероятно, во всем том, что мы называем "Ajax-приложениями", предполагая, что вызов серверного скрипта выполняется асинхронно) становится сервер. И здесь выбор, который вы сделали на стороне клиента, решив использовать JavaScript-объекты и JSON-данные, должен совпасть с соответствующим решением на стороне сервера, где выбирается API для декодирования JSON-данных.

Два этапа внедрения JSON на сервер

Работа с JSON на стороне сервера независимо от используемого серверного языка состоит, по сути, из двух этапов:

  1. Поиск JSON-парсера /инструментария/вспомогательного API для вашего серверного языка
  2. Применение JSON-парсера/инструментария/вспомогательного API для извлечения данных из запроса клиента и преобразования их к виду, понятному серверному скрипту

И это всё, что нужно сделать. Давайте более детально рассмотрим оба этапа.

Поиск JSON-парсера

Лучшим ресурсом для поиска JSON-парсера и других инструментальных программных средств, связанных с JSON, является Web-сайт JSON (см. ссылки в Ресурсах). Помимо обучающей информации о самом формате, на этой странице можно найти ссылки на JSON-инструментарии (tools) и JSON-парсеры под любые платформы: от ASP до Erlang, от Pike до Ruby. Просто найдите там язык, на котором написан ваш скрипт, и закачайте соответствующий инструментарий (toolkit). Скопируйте его себе или обновите с помощью него версию вашего серверного языка или просто установите его (существует много вариантов: всё зависит от того, что вы используете на сервере: C#, PHP, Lisp или что-то другое), главное - чтобы скрипты или программы у вас на сервере могли использовать этот инструментарий.

Например, если вы используете PHP, то достаточно просто обновить его до недавней версии 5.2, в которую по умолчанию включено JSON-расширение. Это, пожалуй, самый простой способ начать работать с JSON, если вы используете PHP. Если же вы используете Java-сервлеты, то проще всего задействовать пакет org.json с сайта json.org. Для этого надо скачать архив json.zip с Web-сайта JSON, скопировать файлы с исходными кодами в компиляционную директорию вашего проекта и соответственно скомпилировать их - и вы уже сможете работать с JSON. Примерно то же самое надо сделать и при использовании других языков; лучший помощник в этом – ваш собственный опыт программирования под соответствующую серверную платформу.

Использование JSON-парсера

После того как необходимый инструментарий установлен, остается только вызвать нужный метод. Например, предположим, что мы используем PHP и модуль JSON-PHP:

// Это лишь фрагмент большого серверного PHP-скрипта 
require_once('JSON.php');

$json = new Services_JSON();

// принимаем POST-данные и декодируем их
$value = $json->decode($GLOBALS['HTTP_RAW_POST_DATA']);

// теперь работаем с переменной $value как с обычными «сырыми» данными PHP

С помощью этого кода мы помещаем все данные (массивы, множественные строки, единичные значения - всё, что было в JSON-структуре с данными) в переменную $value, причём в родном PHP-формате.

Если бы мы использовали на сервере Java-сервлеты и пакет org.json, то код выглядел бы приблизительно так:

public void doPost(HttpServletRequest request, HttpServletResponse response)
  throws ServletException, IOException {

  StringBuffer jb = new StringBuffer();
  String line = null;
  try {
    BufferedReader reader = request.getReader();
    while ((line = reader.readLine()) != null)
      jb.append(line);
  } catch (Exception e) { //сообщение об ошибке }

  try {
    JSONObject jsonObject = new JSONObject(jb.toString());
  } catch (ParseException e) {
    // crash and burn
    throw new IOException("Ошибка при  разборе строки запроса");
  }

  // Работаем с данными, используя методы типа:
  // int someInt = jsonObject.getInt("intParamName");
  // String someString = jsonObject.getString("stringParamName");
  // JSONObject nestedObj = jsonObject.getJSONObject("nestedObjName");
  // JSONArray arr = jsonObject.getJSONArray("arrayParamName");
  // и так далее...
}

Более подробную информацию можно найти в документации к пакету org.json (см. ссылки в разделе Ресурсы). (Замечание: если вы хотите более детально изучить org.json или другие программные средства для работы с JSON, напишите мне на e-mail и сообщите об этом. Ваши отклики помогают мне решить, о чём следует писать дальше!).

Заключение

Теперь вы уже должны знать техническую сторону использования JSON на сервере. Но в этой и предыдущей статьях мне хотелось не только показать несколько технических аспектов, но и убедить вас в том, что JSON – весьма гибкий и мощный формат данных. Даже если вы не будете использовать его в каждом своём приложении, хороший Ajax- и JavaScript-программист всегда должен иметь под рукой этот полезный инструмент и уметь применить его, когда в том возникнет необходимость.

Мне определённо хотелось бы услышать о вашем собственном опыте работы с JSON и том, какие языки, по вашему мнению, хорошо – или может быть не очень – работают с JSON-данными на стороне сервера. Загляните на страницу группы новостей о Java и XML (ссылки в Ресурсах) и расскажите мне об этом. Наслаждайтесь JSON и всей мощью текстовых форматов данных.


Ресурсы для скачивания


Похожие темы


Комментарии

Войдите или зарегистрируйтесь для того чтобы оставлять комментарии или подписаться на них.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Web-архитектура, XML
ArticleID=342696
ArticleTitle=Освоение Ajax: Часть 11. JSON на стороне сервера
publish-date=10012008