Ajax Russia : Аякс по-русски

Свежие новости из мира IT

Введение в JSON

AJAX JSONСреди форматов обмена данными, AJAX программисты часто выделяют JSON (JavaScript Object Notation, "джейсн"), как альтернатива языку XML, а именно потому, что XML больше язык разметки, чем носитель данных. JSON в свою очередь, легкий, человеко-читабельный, текстовый формат для хранения и передачи простых структурированных данных, а так же более комплексных объектов (массивов). В этом уроке мы рассмотрим простой пример формирования данных в JSON средствами PHP, а так же их получение и представление, с помощью JavaScript. Кто еще не понял, это продолжение серии уроков "AJAX PHP поиск" (XML, Prototype).

JSON structure

Чем отличается представление данных в JSON от, допустим, XML. Простой пример:

CODE:
  1. { "players" : [
  2.   { "firstName" : "Ryan", "lastName" : "Campbell", "position" : "S" },
  3.   { "firstName" : "Chris", "lastName" : "Campbell", "position" : "QB" },
  4.   { "firstName" : "Kevin", "lastName" : "Hale", "position" : "DT" }
  5. ]}

Здесь у нас есть элемент players, который в свою очередь является массивом из трех "рядов", а каждый такой "ряд" это массив еще из трех элементов (firstName, lastName, position). Самое интересное то, что в языке JavaScript есть встроенная функция eval(), которая "парсит" (разбирает) такие строки.

Ну например, допустим у нас эти данные хранятся в переменной s (уже в JavaScript):

JavaScript:
  1. var obj = eval("(" + s + ")");

Мы получаем объект obj, который будет хранить все эти данные в очень удобной структуре:

JavaScript:
  1. alert(obj.players[0].firstName); // Ryan
  2. alert(obj.players[1].lastName); // Campbell
  3. alert(obj.players[2].position); // DT

Вот таким образом мы получаем доступ к JSON данным. Формирование таких данных мало чем отличается. Ну например на языке PHP:

PHP:
  1. $a = array();
  2.  
  3. $a["players"][0]["firstName"] = "Ryan";
  4. $a["players"][0]["lastName"] = "Campbell";
  5. $a["players"][0]["position"] = "S";
  6.  
  7. ...
  8.  
  9. $json = new Services_JSON();
  10. echo $json->encode($a);

На входе методу encode() подается любой массив, и метод возвращает закодированный в JSON такой же массив, готовый для передачи куда-либо.

Например..

Вспомним уроки создания AJAX поиска методами XML и Prototype. Попробуем еще разок продублировать этот пример, только уже с использованием JSON для представления данных.

Посмотреть в действии можно здесь:
http://logicerror.pp.ru/upload/ajax_search_json/

Начинаем:

  1. база данных MySQL
  2. html файл для вывода информации (index.html)
  3. AJAX скрипт (script.js)
  4. PHP двигатель (search.php)

В php5 уже встроены функции для работы с JSON данными. Для php4 качаем PEAR библиотеку json.php отсюда:
http://pear.php.net/pepr/pepr-proposal-show.php?id=198

База данных и HTML представление страницы у нас не изменилось совсем (ну кроме заголовка в HTML), так что у кого до сих пор нет, копируем отсюда:
http://www.ajaxrussia.com/archives/ajax-php-search-xml

AJAX

JavaScript:
  1. function getXmlHttp() {
  2.   var xmlhttp;
  3.   try {
  4.     xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
  5.   } catch (e) {
  6.       try {
  7.         xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
  8.       } catch (E) {
  9.       xmlhttp = false;
  10.     }
  11.   }
  12.  
  13.   if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
  14.     xmlhttp = new XMLHttpRequest();
  15.   }
  16.   return xmlhttp;
  17. }
  18.  
  19. function search() {
  20.   var sSearch = document.getElementById("search_input").value;
  21.  
  22.   if (sSearch.length <3)
  23.   {
  24.     alert("Запрос должен быть не короче 3-х символов.");
  25.     return false;
  26.   }
  27.  
  28.   var xmlHttp;
  29.   xmlHttp = getXmlHttp();
  30.  
  31.   var obj = document.getElementById("search_results");
  32.   obj.innerHTML = "";
  33.   var loading = document.getElementById("searching");
  34.   loading.style.display = "block";
  35.  
  36.   xmlHttp.onreadystatechange = function()  {
  37.     if (xmlHttp.readyState == 4)
  38.     {
  39.       loading.style.display = "none";
  40.       var json = eval( "(" + xmlHttp.responseText + ")" );
  41.       for (var i = 0; i <json.entry.length; i++)
  42.       {
  43.         var new_el = document.createElement("div");
  44.         new_el.innerHTML = "<h1>" + json.entry[i].title + "</h1>" + json.entry[i].content;
  45.         new_el.className = "result";
  46.        
  47.         obj.appendChild(new_el);
  48.       }
  49.     }
  50.   }
  51.  
  52.   xmlHttp.open('GET', 'search.php?search='+sSearch+'&rand='+Math.random(), true);
  53.   xmlHttp.send(null);
  54. }

В script.js у нас произошли некоторые изменения в районе обработки и представления данных. Рассмотрим по порядку:

JavaScript:
  1. var json = eval( "(" + xmlHttp.responseText + ")" );

В переменную json, мы помещаем объект полученный функцией eval, которая целиком разбирает текст полученный с запрашиваемой страницы - xmlHttp.responseText (JSON ведь именно в текстовом формате данные хранит, помните?). Таким образом, переменная json у нас теперь полноценный объект с данными результата поиска.

JavaScript:
  1. for (var i = 0; i <json.entry.length; i++)
  2. {
  3.   var new_el = document.createElement("div");
  4.   new_el.innerHTML = "<h1>" + json.entry[i].title + "</h1>" + json.entry[i].content;
  5.   new_el.className = "result";
  6.  
  7.   obj.appendChild(new_el);
  8. }

Здесь, узнав сколько всего записей у нас получено (json.entry.length, где entry у нас массив - поймете когда дойдем до части php), мы в цикле обрабатываем все элементы этих записей. То есть, как и в первом самом уроке, создаем новый элемент div, помещаем в него (.innerHTML) один сформированный результат поиска, присваиваем класс result, ну и наконец приклеиваем к объекту obj (поле для результатов поиска).

Теперь рассмотрим, как мы сформировали JSON данные.

PHP & JSON

PHP:
  1. <?php
  2.   $db = mysql_connect("localhost", "root", "");
  3.   mysql_select_db("ajax_search");
  4.   mysql_query("SET CHARACTER SET utf8");
  5.  
  6.   require("json.php");
  7.  
  8.   header('Content-type: application/json; charset=utf-8');
  9.   header('Cache-Control: no-cache');
  10.  
  11.   $entry = array();
  12.  
  13.   $sString = mysql_real_escape_string($_GET["search"], $db);
  14.  
  15.   $sql="SELECT * FROM `articles` WHERE `title` LIKE '%$sString%' OR `content` LIKE '%$sString%' ORDER BY `id` DESC LIMIT 10";
  16.   $rs=mysql_query($sql,$db);
  17.  
  18.   if (mysql_num_rows($rs)> 0)
  19.   {
  20.     $i = 0;
  21.     while ($row = mysql_fetch_array($rs))
  22.     {
  23.       $content=htmlspecialchars(strip_tags($row["content"]));
  24.       if (mb_strlen($content, "utf-8")> 250) $content = mb_substr($content, 0, 250, "utf-8") . "...";
  25.       $entry["entry"][$i]["title"] = htmlspecialchars($row["title"]);
  26.       $entry["entry"][$i]["content"] = $content;
  27.       $i++;
  28.     }
  29.   }
  30.   else
  31.   {
  32.     $entry["entry"][0]["title"] = "";
  33.     $entry["entry"][0]["content"] = "Ничего не найдено";
  34.   }
  35.  
  36.   $json = new Services_JSON();
  37.   echo $json->encode($entry);
  38. ?>

Подключение к базе данных и составление запроса поиска, думаю хватит уже обсуждать. Перейдем сразу к делу:

PHP:
  1. require("json.php");

Мы работаем на php4, так что обязательно подключаем PEAR библиотеку JSON (в которой и описан класс Services_JSON и методы encode/decode.

PHP:
  1. header('Content-type: application/json; charset=utf-8');

Согласно RFC 4627 JSON данные должны иметь MIME тип application/json, учтите это.

PHP:
  1. $entry = array();

Создаем простой пустой массив $entry. Сюда мы будем записывать наши данные, а потом кодировать в формат JSON.

PHP:
  1. $i = 0;
  2. while ($row = mysql_fetch_array($rs))
  3. {
  4.   $content=htmlspecialchars(strip_tags($row["content"]));
  5.   if (mb_strlen($content, "utf-8")> 250) $content = mb_substr($content, 0, 250, "utf-8") . "...";
  6.  
  7.   $entry["entry"][$i]["title"] = htmlspecialchars($row["title"]);
  8.   $entry["entry"][$i]["content"] = $content;
  9.   $i++;
  10. }

Здесь переменная $i будет служить в качестве счетчика, далее обрабатываем поля title и content из базы данных (как и раньше), и в своеобразной форме записываем в массив $entry. Расскажу о структуре массива. Первый элемент у нас всегда будет "entry" - мы так к нему обращаемся в javascript - json.entry. Второй элемент - порядковый номер результата (счетчик наш), так же используется в js - json.entry[i]. Ну и последние элементы - поля title и content. И таким же образом к ним обращается js - json.entry[i].title и json.entry[i].content.

PHP:
  1. $entry["entry"][0]["title"] = "";
  2. $entry["entry"][0]["content"] = "Ничего не найдено";

В случае если поисковой запрос не дал результатов, мы в массив $entry помещаем всего одну запись - нчиего не найдено.

PHP:
  1. $json = new Services_JSON();
  2. echo $json->encode($entry);

Здесь все просто. Создаем новый объект из класса Services_JSON(), и вызываем функцию encode(), передав наш массив $entry в качестве параметра. Ну и естественно выводим это все.

Заключение

Ну вот, собственно, и все.
По сравнению с XML, JSON более прост и удобен в использовании (особенно тем, кто хорошо ориентируется в массивах), но есть несколько нюансов по безопасности - обязательно проверяйте JSON данные на код javascript перед тем, как использовать его в eval(), т.к. эта функция исполняет javascript код.

Ну а с Prototype можно и не сравнивать, особенно если использовать их в паре - Prototype+JSON. Prototype для удобной работы с AJAX запросами, а JSON для удобного представления данных.

Полезные ссылки

del.icio.us Забобрить!

5 Comments so far

  1. Артём Курапов April 30th, 2008 20:03

    Я не уверен, но помоему PEAR’ная библиотека имела сложности с генерированием сложных вложенных объектов и массивов и приходилось всё переводить в массив.

  2. Константин April 30th, 2008 20:05

    Артём Курапов, ничего страшного, ведь это уже прошлое ;) почти…

  3. Интересующийся May 18th, 2008 08:23

    Константин, а что скажете по поводу скорости обработки JSON по сравнению с XML? Судя по тому, что JSON — нативный формат JavaScript, он должен обрабатываться быстрее, чем парсинг XML.

  4. Константин May 19th, 2008 13:06

    Совершенно верно, JSON обрабатывается гораздо быстрее чем XML.

  5. PitBult June 30th, 2008 16:17

    Спасибо автору, интересная и полезная статья.
    Запостил у себя в блоге. Если найду время, напишу дополнение и свои навыки по этой теме.

Leave a reply