Здравствуйте, товарищи, в этой будем разбирать формат хранения данных JSON.
Для начала общие понятия что же это за формат такой и чем знаменит.
Есть на свете такой формат - xml и всем он хорош. В нём можно хранить любые иерархии объектов любой вложенности, хорошо парсится, легко изменяется. Он с искал применение как и в Web разработке так и в StandAlone приложениях. Но имеет он недостаток - громоздкий слишком. А размер в сфере Web играет ключевую роль.
И вот на свет рождается JSON. Более компактный, более читаемый, более гибкий. И отлично подходит для сериализации массивов/объектов сколь угодной вложенности.
Для работы с этим форматом в PHP предусмотрено 2 замечательные и простые ф-ции:
Кодирует в JSON массив или объект:
string json_encode(mixed $value)
Декодирует JSON в объект или массив (последний флаг указывает на это)
mixed json_decode(string $json, bool $assoc)
* если нет веб сервера под рукой php код можно тестировать тут: http://codepad.org/
Некоторые эксперименты:
Закодируем простой массив:
<?
$test_array = array(-1, -0.5, 0, 0.5, 1, 'string', 'string with "quotes"');
echo json_encode($test_array);
?>
[-1,-0.5,0,0.5,1,"string","string with \"quotes\""]
Как мы видим числа в JSON хранятся без кавычек, и спец символы экранируются символом обратного слеша.
Закодируем структурированные данные:
<?
# Наш массив для теста
$test_array = array();
$test_array[] = array(
'name' => 'Ivan',
'status' => 'online'
);
$test_array[] = array(
'name' => 'Stepan',
'status' => 'offline'
);
$test_array[] = array(
'name' => 'Igor',
'status' => 'busy'
);
echo json_encode($test_array);
?>
На выходе получаем:
[
{"name":"Ivan","status":"online"},
{"name":"Stepan","status":"offline"},
{"name":"Igor","status":"busy"}
]
Довольно компактно и удобочитаемо. (Табы были расставлены для удобности восприятия и на парсинг они не влияют)
"[...]" - объект
{...} - поле
Теперь давайте попробуем раскодировать нашу JSON-структуру:
<?
# Наши JSON данные
$json = '
[
{"name":"Ivan","status":"online"},
{"name":"Stepan","status":"offline"},
{"name":"Igor","status":"busy"}
]
';
$result = json_decode($json);
print_r($result);
Результат:
Array
(
[0] => stdClass Object
(
[name] => Ivan
[status] => online
)
[1] => stdClass Object
(
[name] => Stepan
[status] => offline
)
[2] => stdClass Object
(
[name] => Igor
[status] => busy
)
)
Как мы видим PHP вернул набор неких stdClass`ов. Что же это за класс такой? Дело в том, что JSON изначально разрабатывался для передачи именно классов в материализованном виде. Вот и php сразу создаёт простейший класс без методов с полученными полями из json.
Теперь к ним можно обращаться из php так:
<?
# Наши JSON данные
$json = '
[
{"name":"Ivan","status":"online"},
{"name":"Stepan","status":"offline"},
{"name":"Igor","status":"busy"}
]
';
$result = json_decode($json);
echo $result[0]->name . PHP_EOL;
echo $result[1]->status. PHP_EOL;
Ответ:
* тут я использовал константу PHP_EOL, которая содержит код переноса каретки актуальный для операционной системы сервера.
А что если нам не нужны эти странные stdClass`ы? Что если устраивают только массивы? Не беда, у ф-ции json_decode есть второй не обязательны параметр $assoc. Поставьте TRUE и будут вам массивы.
Теперь давайте напишем небольшое приложение.
Представим что есть некая база данных разработчиков, где прописан язык программирования и текущий статус (занят/не занят) для каждого разработчика и нам надо реализовать интерфейс выборки разработчиков по катигории языка программирования и статуса занят/не занят.
Серверная часть будет на PHP.
Клиентская часть - веб страница с JavaScript`ом.
Общение между частями будет происходить следующим образом:
На клиенте:- Пользователь жмёт пимпу.
- JavaScript формирует JSON на отправку и отсылает.
- Ожидание ответа.
- После того как ответ пришёл выводим результат на веб страницу.
На сервере:- Разбираем пришедшие данные
- Ищем в бд сотрудника по критерию принятому от клиента
- Собираем JSON структуру
- Выплёвываем клиенту
Для начала сделаем нашу базу данных :
db.txt
[{"name":"Impersonalis","busy":true,"lang":"C++"},{"name":"SBJoker","busy":false,"lang":"C++"},{"name":"ABTOMAT","busy":true,"lang":"php"},{"name":"Randomize","busy":false,"lang":"php"},{"name":"Harter","busy":true,"lang":"Blitz3D"},{"name":"Hurrit","busy":true,"lang":"Blitz3D"},{"name":"baton4ik","busy":true,"lang":"BlitzMax"},{"name":".Squid","busy":true,"lang":"C++"},{"name":"MoKa","busy":true,"lang":"php"}]
* не обижаемся :B
(кодировка пока пофиг ибо текст у нас только английский, однако рекомендую utf8 везде всегда и при любой погоде)
Теперь давайте опишем php сценарий который будет принимать запросы и выдавать результат в формате json.
data.php
<?
$request = (object)$_GET;
/*
$request['lang'] - язык программирования
если пусто - пофиг
$request['busy'] - занятость разработчика
-1 - пофиг
0 - не занят
1 - занят
*/
// Открываем нашу базу данных
$db = file_get_contents('db.txt');
$db = stripcslashes($db); // Если у вас включен magic_quotes_gpc на сервере
$db = json_decode($db); // Да, да. Фигачим в ту же переменную
// Это будем заполнять по мере нахождения
$result = array();
// Ищем в базе данных программеров по языку программирования
// Если пофиг на язык то суём всех прогеров в результат тобеж помещаем весть db в result
if (empty($request->lang)){
$result = $db;
// Иначе делаем выборку
}else{
foreach($db as $programmer){
// Если языки совпали
if ($programmer->lang == $request->lang){
// добавляем программера в результат
$result[] = $programmer;
}
}
}
// Теперь если требуемый статус не -1 то убираем из таблицы всех прогеров у которых статус не соответствует требуемому
if ($request->busy != -1){
foreach($result as $key => $programmer){
// $key - ключ(указатель) на позицию значения в массиве
// Если статус занятости не тот который нам нужен
if ($programmer->busy!=$request->busy){
// нах такого прогера из результата
unset($result[$key]);
}
}
}
// Кодируем и выдаём результат
die( json_encode($result) );
// Die завершает нннах скрипт чтоб его не инклудили и тд
Сразу оговорюсь - для составления асинхронных AJAX запросов с веб страницы мы будем использовать JavaScript фреймворк jQuery. Просто без него придётся городить лес кода чтоб всё работало кроссбраузерно и тд.
Код веб морды:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<!-- Stylesheets -->
<style type="text/css">
body{background: lightgray}
#toolbar{ padding: 5px; width: 900px; margin: 15px auto; border: 1px solid black; background: white;}
#result_wrap{ padding: 5px; width: 900px; margin: 15px auto; border: 1px solid black; background: white;}
#result_table{ width: 100%;}
#result_table td{ border: 1px dotted gray; }
</style>
<!-- Javascripts -->
<script type="text/javascript" src="http://yandex.st/jquery/1.6.4/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$('form').submit(function(){
// Собираем наш json на отправку
var json ={
'lang' : $('#lang').val(), // Получаем значение элемента lang из формы
'busy' : $('#busy').val() // получаем значение элемента busy из формы
};
// Отправлаяем JSON методом post
$.getJSON("data.php",
json,
function(data) {
// Очищаем tbody таблицы от результатов
$('#result').empty();
$.each(data, function(i,item){
// Если item.busy = true то "Да, занят" иначе "Нет, не занят"
item.busy = (item.busy == true)? 'Да' : 'Нет';
$("<tr>"+
"<td>"+ item.name +"</td>" +
"<td>"+ item.lang +"</td>" +
"<td>"+ item.busy +"</td>" +
"</tr>").appendTo('#result');
})
}
);
// чтоб форма не срабатывала
return false;
})
})
</script>
</head>
<body>
<div id="toolbar">
<form action="" method="post">
Язык программирования:
<select id="lang">
<option value="">Всё равно</option>
<option value="Blitz3D">Blitz3D</option>
<option value="php">php</option>
<option value="Cpp">Cpp</option>
<option value="BlitzMax">BlitzMax</option>
</select>
Занятость:
<select id="busy">
<option value="-1">Всё равно</option>
<option value="1">Занят</option>
<option value="0">Свободен</option>
</select>
<input type="submit" value="Получить данные" />
</form>
</div>
<div id="result_wrap">
<table id="result_table">
<thead>
<tr>
<td>Ник</td>
<td>Язык программирования</td>
<td>Занят</td>
</tr>
</thead>
<tbody id="result">
</tbody>
</table>
</div>
</body>
</html>
Рабочий пример тут:
http://randomize.boolean.name/examples/json/index.html
Также скачать все скрипты можно по этой ссылке:
http://randomize.boolean.name/examples/json/all.7z
Тема JSON раскрыта не полностью. В следующей статейке я покажу применение JSON в standalone приложениях.