forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   PHP / MySQL (http://forum.boolean.name/forumdisplay.php?f=135)
-   -   Введение в JSON (http://forum.boolean.name/showthread.php?t=15785)

Randomize 06.11.2011 04:48

Введение в JSON
 
Здравствуйте, товарищи, в этой будем разбирать формат хранения данных 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/

Некоторые эксперименты:
Закодируем простой массив:
PHP код:

<?
$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 хранятся без кавычек, и спец символы экранируются символом обратного слеша.

Закодируем структурированные данные:
PHP код:

<?
# Наш массив для теста
$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-структуру:
PHP код:

<?
# Наши 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 так:
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;

Ответ:
Код:

Ivan
offline

* тут я использовал константу 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
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>                       
                       
                        &nbsp;&nbsp;
                       
                        Занятость:
                        <select id="busy">
                                <option value="-1">Всё равно</option>
                                <option value="1">Занят</option>
                                <option value="0">Свободен</option>
                        </select>
                       
                        &nbsp;&nbsp;
                       
                        <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 приложениях.

moka 06.11.2011 05:25

Ответ: Введение в JSON
 
php.. Это оскорбительно! :(

C#


Статья хорошая. Рассмотрен с точки зрения веба, и применения как замену xml'у. Можно даже было для сложности добавить заместо одного языка, массив языков.

.Squid 06.11.2011 05:35

Ответ: Введение в JSON
 
Цитата:

Сообщение от MoKa (Сообщение 208540)
php.. Это оскорбительно! :(

Да ладно. Оскорбительно утверждать, что это оскорбительно (:
К тому же
Цитата:

Сообщение от Randomize (Сообщение 208537)
* не обижаемся :B

ЗЫ. Годная статья. Плохо, что грамматика хромает. "сискал", "громосткий" : (. Дальше старался не обращать внимания.

Randomize 06.11.2011 05:57

Ответ: Введение в JSON
 
Цитата:

Сообщение от .Squid (Сообщение 208541)
Плохо, что грамматика хромает. "сискал", "громосткий"

Спасибо. Писал без спеллчека в notepad++. Сейчас перечитаю и проведу работу над ошибками (пока сам особо не читал :-D)

Цитата:

Сообщение от MoKa
php.. Это оскорбительно! :(


C#

I fix it, но только в демке :P.

Цитата:

Сообщение от MoKa (Сообщение 208540)
Можно даже было для сложности добавить заместо одного языка, массив языков.

Угу, я об этом думал, но если делать, то делать капитально, не так ли? А значит нужен класс БД на json файлах где 1 файл - 1 таблица. Каждому языку и прогеру свой id. Отдельный тейбл на связь многие ко многим. И всё на чистом php :-D

treycerok 24.12.2011 23:35

Ответ: Введение в JSON
 
Хорошая статья, не смотря на то.что и знаю работу JSON, но плюс заслуженный :) даже в двух сбщ


Часовой пояс GMT +4, время: 05:12.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot