JSON в php

JSON это простой формат для сериализации данных в javascript, т.е. представления пременных в виде строки. Аналогично в php например есть функция serialize(), а в Java - RMI, в .NET - COM (если я не ошибаюсь), ну а в обобщённом виде - XML.

Лёгкий вес

Когда php-программисты ещё не знали о лёгком весе JSON, то для переносимости формата использовали XML. Так делает например FCKeditor до сих пор при получении списка в ресурс-менеджере. Ещё как есть плохой вариант - передавать сразу готовый HTML код. Но размер лишних данных в таком случае растёт в линейной прогрессии с коэффициентом полезные данные/тэги HTML.

Генерация в PHP

На серверной части в php 4 по умолчанию json отключён, но его можно попробовать включить..

dl(json.so); $strToSend=json_encode($objToEncode);

Ещё вариант - использовать объект Services_JSON из громоздкого PEAR.

require_once('json.php'); $json = new Services_JSON(); $strToSend=$json->encode($objToEncode);

Но как правило первый вариант не работает, а второй странно ведёт себя с кодированием utf8. Поэтому мне пришлось немного дописать функцию до варианта, правильно кодирующий new-line символы:

function array2json($arr) { $parts = array(); $is_list = false; if (!is_array($arr)) return; if (count($arr)<1) return '{}'; //Find out if the given array is a numerical array $keys = array_keys($arr); $max_length = count($arr)-1; if(($keys[0] == 0) and ($keys[$max_length] == $max_length)) {//See if the first key is 0 and last key is length - 1 $is_list = true; for($i=0; $i<count($keys); $i++) { //See if each key correspondes to its position if($i != $keys[$i]) { //A key fails at position check. $is_list = false; //It is an associative array. break; } } } foreach($arr as $key=>$value) { if(is_array($value)) { //Custom handling for arrays if($is_list) $parts[] = array2json($value); /* :RECURSION: */ else $parts[] = '"' . $key . '":' . array2json($value); /* :RECURSION: */ } else { $str = ''; if(!$is_list) $str = '"' . $key . '":'; //Custom handling for multiple data types if(is_numeric($value)) $str .= $value; //Numbers elseif($value === false) $str .= 'false'; //The booleans elseif($value === true) $str .= 'true'; else $str .= '"' . addslashes($value) . '"'; //All other things // :TODO: Is there any more datatype we should be in the lookout for? (Object?) $parts[] = $str; } } $json = implode(',',$parts); if($is_list) return '[' . $json . ']';//Return numerical JSON return '{' . $json . '}';//Return associative JSON }

Приготавливаемся принять в браузере

Для того что-бы IE понял правильно utf-8 кодировку, надо указать заголовки. Данные можно передавать как обычным текстом, так и заголовками (что-бы из браузера нельзя было напрямую это увидеть)

header('Content-Type: application/json; charset=utf-8'); header('X-JSON: '.$myJsonData);

В Javascript получаем текст и декодируем его в данные функцией eval. Также не забываем преобразовывать символы новой строки, если они встречаются в данных. Во многих javascript-библиотеках функции для работы с json, сериализацией форм и прочая уже есть.

//пример для prototype.js
json = eval(t.getResponseHeader('X-JSON'));
//Пример для jQuery
$.getJSON('/someJsonURL',function(json){
json.descr=json.descr.replace(/\\n/g,"<br />");
json.descr=json.descr.replace(/\\t/g,"\t");
}

По теме - обязательно посмотрите JSON saga о том как стандарт вводился.

RSS

Комментарии

  • Odem
    Спасибо! Интересная и полезная статья!
  • merlex
    А как на счет обратного преобразования? Из ЖСОН в ПХП?
  • Артём Курапов
    Интересный вопрос. Ну в обычных условиях это ненадо, потому что один параметр в виде JSON не передают в AJAX-е, потому что всё можно по отдельности в POST или GET передать.
    Самый простой вариант это наверно делать explode по запятым, а потом по двоеточиям с убиранием фигурных скобок и кавычек. Не сталкивался увы.
  • Григорий Кочанов
    RTFM :)
    http://ua2.php.net/manual/ru/function.json-decode.php
  • Ruscon
    Из php в JSON
    $json->encode($php_arr)
    Из JSON в php
    $json->decode($json_arr);
  • Poster
    Эти функции некоректно работают с кирилицей
  • Григорий Кочанов
    Если кто не в курсе, поддержка JSON включена в PHP по умолчанию начиная с PHP 5.2.0
    http://ua2.php.net/manual/ru/json.setup.php

    Для версии на Windows может быть нужно подправить php.ini и включить json.so - так же, как вы включаете mysql, curl, gd
    Но эмулировать его не стоит :)
  • Артём Курапов
    Да никто и не спорит, читайте статью внимательней.
  • Григорий Кочанов
    кажется, уточнения "в PHP 4" вчера не было ... (или я ошибаюсь?)
    а то мне сотрудник эту статью показал как объяснение, зачем он написал свой json_encode на 5.2.6 :)
  • Артём Курапов
    Четвёрку я добавил, да (что-бы в будующем народ не спотыкался), но это не отменяет в самом начале сразу же упоминания json_encode. Приятно что меня за авторитетный источник считают, но ему тоже надо было вчитываться :)
  • Алексей
    Немного переписал:
    * убрал кусок "//It is an associative array.", тем более там была ошибка из-за него json для array('a'=>'b', 'c'=>'d', 'e'=>array('o'=>'p')) выдавал неверный результат. Я там ошибку нашёл, (она исправляется === вместо == на 10-ой строке), но мне кажется, привильнее записывать ключи что ассоциативного массива.
    * добавил замену служебных символов
    проверил на своём проекте, вроде бы всё ok, а Services_JSON выкинул :-)
    function json_encode($arr) { $parts = array(); if (!is_array($arr)) return; if (count($arr) === 0) return '{}'; $keys = array_keys($arr); foreach($keys as $key) { if (is_array($arr[$key])) { //Custom handling for arrays $parts[] = '"' . $key . '":' . json_encode($arr[$key]); /* :RECURSION: */ } else { $str = '"'.$key.'":'; //Custom handling for multiple data types if (is_numeric($arr[$key])) $str .= $arr[$key]; //Numbers elseif ($arr[$key] === false) $str .= 'false'; //The booleans elseif ($arr[$key] === true) $str .= 'true'; else $str .= '"'.strtr($arr[$key], array('\\'=>'\\\\', '/'=>'\/', '"'=>'\"', "\b"=>'\b', "\t"=>'\t', "\n"=>'\n', "\f"=>'\f', "\r"=>'\r') ).'"'; //All other things $parts[] = $str; } } return '{'.implode(',', $parts).'}'; //Return associative JSON }
  • Михаил
    Супер! То что искал! Спасибо Алексей!
  • Svyatoslavik
    почемут то не работает ваша функция как надо, в mootools Json decode не работает для нее за то опубликованая в статье работает как надо, так что пересмотрите свой код еще раз...
    спасибо автору
  • Max
    Спасибище
  • vidok
    Автору большое спасибо. Очень познавательная информация
  • Englishelp
    Круто, наконец-то адекватная статья по JSON в PHP. Спасибо!
  • Виктор
    Проблемка с даблом.
    Вот это поможет
    //Custom handling for multiple data types if(is_numeric($value)) { if (is_double($value)) { $str .= '"' . $value . '"'; } else { $str .= $value; } }