За последние 24 часа нас посетили 17940 программистов и 1613 роботов. Сейчас ищут 1454 программиста ...

PHP массивы и объекты в JSON формат

Тема в разделе "Решения, алгоритмы", создана пользователем Psih, 21 май 2008.

  1. Psih

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    Написал небольшой классик для перекодирования PHP массивов и объектов с любыми данными (за исключением ресурсов конечно) в JSON.
    PHP:
    1. <?php
    2.  
    3. class JSONHelper {
    4.  
    5.     var $match = array('"', '\\', '/', "\n", "\r");
    6.     var $replace = array('\"', '\\\\', '\/', '\\n', '\\r');
    7.    
    8.    
    9.         /**
    10.      * Object constructor
    11.      *
    12.      * @return JSONHelper
    13.      */
    14.     function JSONHelper () {
    15.         return $this;
    16.     }
    17.     //-----------------------------------------------------------------------------
    18.    
    19.    
    20.     /**
    21.      * Parse structure to JSON
    22.      *
    23.      * @param mixed $data
    24.      * @return string
    25.      */
    26.     function parse($data) {
    27.         return '('.$this->encode($data).')';
    28.     }
    29.     //-----------------------------------------------------------------------------
    30.    
    31.    
    32.     /**
    33.      * Converts PHP variable to JSON string
    34.      * Can convert any PHP variable with any content to correct JSON structure
    35.      *
    36.      * @param mixed $data Data to convert
    37.      * @return string
    38.      */
    39.     function encode($data) {
    40.        
    41.         $type = $this->getType($data);
    42.        
    43.         switch ($type) {
    44.             case 'object':
    45.                 $data = '{'.$this->processData($data, $type).'}';
    46.                 break;
    47.             case 'array':
    48.                 $data = '['.$this->processData($data, $type).']';  
    49.                 break;
    50.             case 'number':
    51.                 $data = $data;
    52.                 break;
    53.             case 'string':
    54.                 $data = '"'.$this->escape($data).'"';
    55.                 break;
    56.             case 'boolean':
    57.                 $data = ($data) ? 'true' : 'false';
    58.                 break;
    59.             case 'null':
    60.                 $data = 'null';
    61.                 break;
    62.         }
    63.         return $data;
    64.     }
    65.     //-----------------------------------------------------------------------------
    66.  
    67.    
    68.     /**
    69.      * Enter description here...
    70.      *
    71.      * @param unknown_type $input
    72.      * @param unknown_type $type
    73.      * @return unknown
    74.      */
    75.     function processData($data, $type) {
    76.        
    77.         $output = Array();
    78.         // If data is an object - it should be converted as a key => value pair
    79.         if ($type == 'object'){
    80.             foreach($data as $key => $value) {         
    81.                 $output[] = '"'.$key.'": '.$this->encode($value);
    82.             }
    83.         } else {
    84.             foreach($data as $key => $value) {
    85.                 $output[] = $this->encode($value);
    86.             }
    87.         }
    88.         return implode(',', $output);;
    89.     }
    90.     //-----------------------------------------------------------------------------
    91.    
    92.    
    93.     /**
    94.      * Function determines type of variable
    95.      *
    96.      * @param unknown_type $data
    97.      * @return unknown
    98.      */
    99.     function getType(&$data){
    100.        
    101.         if (is_object($data)) {
    102.             $type = 'object';
    103.         } elseif (is_array($data)) {
    104.             // If array is assoc it should be processed as an object
    105.             if($this->is_assoc($data)) {
    106.                 $type = 'object';
    107.             } else {
    108.                 $type = 'array';
    109.             }
    110.         } elseif (is_numeric($data)) {
    111.             $type = 'number';
    112.         } elseif(is_string($data)) {
    113.             $type = 'string';
    114.         } elseif(is_bool($data)) {
    115.             $type = 'boolean';
    116.         } elseif(is_null($data)) {
    117.             $type = 'null';
    118.         } else {
    119.             $type = 'string';
    120.         }
    121.         return $type;
    122.     }
    123.     //-----------------------------------------------------------------------------
    124.    
    125.    
    126.     /**
    127.      * Function determines if array is associative
    128.      *
    129.      * @param array $array
    130.      * @return bool
    131.      */
    132.     function is_assoc($array) {
    133.         // We do that by sorting array keys in reverse (numbers go before other symbols)
    134.         // and probing first element key. 99.9% it will be a string key.
    135.         krsort($array, SORT_STRING);
    136.         return !is_numeric(key($array));
    137.     }
    138.     //-----------------------------------------------------------------------------
    139.    
    140.    
    141.     /**
    142.      * Escapes special characters
    143.      * Function escapes ", \, /, \n and \r symbols so that not to cause JavaScript error or
    144.      * data loss
    145.      *
    146.      * @param string $string
    147.      * @return string
    148.      */
    149.     function escape($string) {
    150.         return str_replace($this->match, $this->replace, $string);
    151.     }
    152.     //-----------------------------------------------------------------------------
    153. }
    Использовать проще пареной репы
    PHP:
    1. <?php
    2. $array = Array(10, 20, Array('bla' => 'blabla', 'blah' => 'double bla'), Array('asdfc23434', '3435435');
    3. $json = new JSONHelper();
    4. echo $json->parse($array);
    5.  
    Всё что надо сделать на стороне JS это
    [js]var phpData = eval(responce.responseText);[/js]
     
  2. Ивашка

    Ивашка Активный пользователь

    С нами с:
    29 авг 2007
    Сообщения:
    96
    Симпатии:
    0
    Адрес:
    Щёкино/Тула
    Функции нынче не в моде? :)

    Ну и насчет типов тоже стоит задуматься.
     
  3. Psih

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    Ивашка
    Оно даже не работает на таком массиве:
    PHP:
    1. <?php
    2. $array = Array("blablabla" => Array(10, 20, Array('bla' => 'blabla', 'blah' => 'double bla'), Array('asdfc23434', '3435435')), "sdfcasdf", "asdfdsf", false);
    3.  
    1). Invalid label получается, потому что JSON строку необходимо заключать в ( ).
    2). Числовые значения в " " в JS не переводятся автоматом из строк в числа, вы явно не знаете систему кастинга в JS. что будет string + integer в JS ? Будет тоже самое что string . integer в PHP - они склеятся так как операция + в JavaScript является как сложением, так и слиянием строк.
    3). Нам явно не нужно str_replace для integer и float.
    4). Зачем для $k (key) вызывать рекурсивно php2js... ?

    Ну и есть пара глупостей которые больше относятся к стилю написания, к примеру явная несуразица с применением for и деланием count масиву на каждой итерации...
    PHP:
    1. <?php
    2. foreach ($a as $key => &$value)
    3. {
    4.     if (is_string($key))
    5.     {
    6.          $isList;
    7.          break;
    8.     }
    9. }
     
  4. Ивашка

    Ивашка Активный пользователь

    С нами с:
    29 авг 2007
    Сообщения:
    96
    Симпатии:
    0
    Адрес:
    Щёкино/Тула
    В общем, так.
    Да ну?
    PHP:
    1. <?
    2. $array = Array("blablabla" => Array(10, 20, Array('bla' => 'blabla', 'blah' => 'double bla'), Array('asdfc23434', '3435435')), "sdfcasdf", "asdfdsf", false);
    3. ?><script type="text/javascript">
    4. //<![CDATA[
    5. var response = '<?=php2js($array)?>'; // типа с сервера пришло
    6.  
    7. var o = null;
    8.  
    9. eval('o = '+response);
    10.  
    11. alert(o.blablabla[2].bla);
    12.  
    13. //]]>
    14. </script>
    У меня выдает "blabla" а у вас?

    Сфигали? Т.е. так ли оно необходимо?
    [js]var a = {};
    var b = ({});
    [/js]
    Наличие ExpressionStatement во втором случае нам ничего не дает. Да и при желании, дописать две скобочки мы всегда можем.

    Я в курсе :)
    С php так работать удобнее, и дурные ошибки не будут вылезать

    Т.е. по вашему, 123.45 и 123,45 js-интерпретатор разберет как одно и то-же число?


    Ну хотя бы затем, что $k может содержать что-нибудь из $jsonReplaces.

    Насчет стиля оспаривать не буду :) да и не в этом дело. Я просто хотел сказать, что все можно сделать гораздо проще.
     
  5. 440Hz

    440Hz Старожил
    Команда форума Модератор

    С нами с:
    21 дек 2012
    Сообщения:
    8.003
    Симпатии:
    1
    Адрес:
    Оттуда
    я бы посоветовал все-таки
    $json = JSONHelper::parse($a);


    коротко и ясно. а то создай экземпляр, вызови метод. операция атомарная. по уму вообще функцией все сделать, что люди и делают.
    ггг
     
  6. Psih

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    440Hz
    А ты глянь PEAR Serices_JSON... :D

    По сути писал как часть системы - там объектами всё. Выложил как было. Кому надо - заюзает, кто захочет - переделает.
     
  7. Ti

    Ti Активный пользователь

    С нами с:
    3 июл 2006
    Сообщения:
    2.378
    Симпатии:
    1
    Адрес:
    d1.ru, Екатеринбург
  8. Ивашка

    Ивашка Активный пользователь

    С нами с:
    29 авг 2007
    Сообщения:
    96
    Симпатии:
    0
    Адрес:
    Щёкино/Тула
    Ti
    Расширение работает только с UTF-8 и не везде есть.
     
  9. Ti

    Ti Активный пользователь

    С нами с:
    3 июл 2006
    Сообщения:
    2.378
    Симпатии:
    1
    Адрес:
    d1.ru, Екатеринбург
    1. не везде есть PHP > 3, так давайте писать на Brainfuck?
    2. utf-8 давно уже очень стандартная кодировка де-факто

    Нативное расширение для PHP приоритетный выбор для решения вопроса.
    Темболее
     
  10. Ивашка

    Ивашка Активный пользователь

    С нами с:
    29 авг 2007
    Сообщения:
    96
    Симпатии:
    0
    Адрес:
    Щёкино/Тула
    Согласен. Вот еще бы все хостеры наше мнение разделяли...
     
  11. vasa_c

    vasa_c Активный пользователь

    С нами с:
    22 мар 2006
    Сообщения:
    1.760
    Симпатии:
    0
    Адрес:
    гор.Ленинград
    json_encode любит русские слова кодировать, как \u0123\u...