За последние 24 часа нас посетили 19909 программистов и 1694 робота. Сейчас ищут 1733 программиста ...

Распарсить json-подобную строку

Тема в разделе "Регулярные выражения", создана пользователем Koc, 22 май 2009.

  1. Koc

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

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    есть строки
    Код (Text):
    1.  
    2.         'template'  : "/goodsViev.htm",
    3.         'show'  : "yes"
    Код (Text):
    1.  
    2. 'template': '/listGoods.htm'
    Код (Text):
    1.  
    2.  "orderBy":'rank'
    нужно их преобразовать к массиву. Как видно кавычки могут быть разные, отступы тоже. Хелп плизз.
     
  2. Koc

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

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    допоможiть!
    Сейчас написал вот так:
    PHP:
    1. <?
    2.     private static function unparseSettings($settings)
    3.     {
    4.         $pattern = '#(\'|")(.*?)("|\')#si';
    5.         preg_match_all($pattern, $settings, $matches);
    6.        
    7.         $keys = $vals = array(NULL);
    8.        
    9.         foreach ($matches[2] as $k => $v) {
    10.             if($k % 2 == 0)
    11.                 $keys[] = $v;
    12.             else
    13.                 $vals[] = $v;
    14.         }
    15.        
    16.         return array_combine($keys, $vals);
    17.     }
    18.  
    но это же калл.
     
  3. Apple

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

    С нами с:
    13 янв 2007
    Сообщения:
    4.984
    Симпатии:
    2
    Никогда не работал с форматом JSON, но что если попробовать preg_split по элементу разделителя , , которая не находится в двойных кавычках и является предшествующей следующей инструкции.
    Далее получаем обычную строку со значением инсекс -> значение и забиваем её в массив.
    Но, поскольку спецификацию JSON я не знаю и сужу только по тому, что вижу, возможно вариант мой неверный.
     
  4. Cron

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

    С нами с:
    10 июл 2008
    Сообщения:
    289
    Симпатии:
    0
    Адрес:
    Украина, Сумы
    Весь вопрос в том, могут ли в середине кавычек встречаться другие кавычки? Т.е. например такое:

    'show' : "yes 'yes' no"

    Если такого не бывает, то:
    1. Все двойные кавычки меняем на одинарные
    2. Убираем все пробельные символы по обе стороны от двоеточия
    3. Парсим простой регуляркой - точно не скажу, не тестил
    '/\'(.+)\'\:\'(.+)\'/'
    как-то так.

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

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

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    Apple
    та это у меня не совсем JSON, но похоже. json_decode не подходит, так как у меня невесть где пробельные символы находятся, кавычки разные и еще много чего.

    Cron
    я еще не знаю, наверно не будет кавычек в кавычках.

    Кстати я тоже думал разбить по ,, потом по : и снять кавычки. Но пока в сторону регулярки думаю.

    зызы: а как думаете, что это такое будет в итоге?
     
  6. Apple

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

    С нами с:
    13 янв 2007
    Сообщения:
    4.984
    Симпатии:
    2
    PHP:
    1. <?php
    2.  
    3. $data = array();
    4. $json = file_get_contents('json.txt'); // твой файл с текстом выше
    5.  
    6. /**
    7.  * Разбиваем строку
    8.  */
    9. $json = preg_split('/["\'],\s*\r?\n/im', $json);
    10.  
    11.  
    12. /**
    13.  * Разбираем полученный массив по примеру ключ => значение
    14.  * и пишем в массив $data
    15.  */
    16. foreach($json as $exp){
    17.     $tmp = preg_split('/(?<=["\'])\s*:\s*(?=["\'])/is', $exp);
    18.    
    19.     $tmp[0] = preg_replace('/^["\']*(.*?)["\']*$/is', '$1', $tmp[0]);
    20.     $tmp[1] = preg_replace('/^["\']*(.*?)["\']*$/is', '$1', $tmp[1]);
    21.    
    22.     $data[$tmp[0]] = $tmp[1];
    23. }
    24.  
    25. /**
    26.  * Выводим пример
    27.  */
    28. echo $data['template'];
    29.  
    30. ?>
    Следует отметить, что разбивает файл правильно, вне зависимости от типа кавычек и уровня их вложенности.
    Тестировал, всё вроде работает.
     
  7. Apple

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

    С нами с:
    13 янв 2007
    Сообщения:
    4.984
    Симпатии:
    2
    Забыл приложить файл json.txt

    Код (Text):
    1. 'template'   : "/goodsViev.htm",
    2. 'show'       : "yes",
    3. "orderBy"    :'rank'
     
  8. Koc

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

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    Apple
    оу, спасибо, но у меня чуточку некорректно работает
    скармливаю
    Код (Text):
    1.  
    2.                     'someCV_var'    :   "ss",
    3.                     "aaa"            :"aa"
    получаю
    Код (Text):
    1. Array
    2. (
    3.     [
    4.                     'someCV_var] => ss
    5.     [                   "aaa] => aa"
    6.                
    7. )
    скармливаю
    Код (Text):
    1.                     "e1a"            : "info:3"
    получаю
    Код (Text):
    1.                 Array
    2. (
    3.     [
    4.                     "e1a] => info:3"
    5.                
    То есть время от времени проскакивают лишние символы кавычек - в начале ключа элемента массива/в конце значения
     
  9. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    json_decode
     
  10. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    а ещё можно так
    PHP:
    1. <?
    2. $str=preg_replace("#(?<=[\"\'])\s*:\s*(?=[\"\'])#is","=>",$str);
    3. eval("\$result=array(".$str.");");
    4. ?>
     
  11. Apple

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

    С нами с:
    13 янв 2007
    Сообщения:
    4.984
    Симпатии:
    2
    А, так там пробелы начальные нефиксированные.
    Ну ничего, переписал:

    PHP:
    1. <?php
    2.  
    3. $data = array();
    4. $json = file_get_contents('json.txt');
    5.  
    6. /**
    7.  * Разбиваем строку
    8.  */
    9. $json = preg_split('/["\'],\s*\r?\n/im', $json);
    10.  
    11.  
    12. /**
    13.  * Разбираем полученный массив по примеру ключ => значение
    14.  * и пишем в массив $data
    15.  */
    16. foreach($json as $exp){
    17.     $tmp = preg_split('/(?<=["\'])\s*:\s*(?=["\'])/is', $exp);
    18.    
    19.     $tmp[0] = preg_replace('/^["\']*(.*?)["\']*$/is', '$1', trim($tmp[0]));
    20.     $tmp[1] = preg_replace('/^["\']*(.*?)["\']*$/is', '$1', trim($tmp[1]));
    21.    
    22.     $data[$tmp[0]] = $tmp[1];
    23. }
    24.  
    25. /**
    26.  * Выводим пример
    27.  */
    28. echo '<pre>';
    29. print_r($data);
    30.  
    31. ?>
    Теперь работает, включая кавычки :)
     
  12. Koc

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

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    ага, большое спасибо, Apple
    я тоже поправил, вроде работает:
    PHP:
    1. <?
    2. $json = preg_split('/["\'],\s*(\r|\n|)/im', $settings); // Так более корректно, ибо после запятой может отсутствовать перенос коретки: 'var1':'foo',"var2": 'bar'
    3.  
    4. foreach ($json as $exp) {
    5.     $tmp = preg_split('/(?<=["\'])\s*:\s*(?=["\'])/is', $exp);
    6.     $data[trim($tmp[0], "\n\t\r'\"")] = trim($tmp[1], "\n\t\r'\"");
    7. }
    8. return $data;
    9.  
    Mr.M.I.T.
    json_decode не подходит и я уже объяснил поцчему, пздц, ты хоть бы тред прочитал прежде чем писать. А eval не есть гуд.
     
  13. Apple

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

    С нами с:
    13 янв 2007
    Сообщения:
    4.984
    Симпатии:
    2
    Koc
    Твой код вложенные кавычки режет, вот поэтому я так не хотел писать :)
    Но, впрочем, тебе лучше знать спецификацию данных и требования к строкам.

    ev[a=i]l :)
     
  14. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    чем вам евал всем не угодил?
     
  15. Koc

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

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    окончательный вариант:

    PHP:
    1. <?
    2. private static function unparseSettings($settings)
    3. {
    4.     // разбиение построчно
    5.     $json = preg_split('/["\'],\s*(\r|\n|)/im', $settings);
    6.      
    7.     foreach ($json as $exp) {
    8.         // Разбиение поэлементно и обрезка лишних пробельных символов
    9.         $tmp = array_map('trim', preg_split('/(?<=["\'])\s*:\s*(?=["\'])/is', $exp));
    10.        
    11.         $pattern = '#^["\']*(.*?)["\']*$#is';
    12.         // обрезка кавычек по бокам
    13.         $tmp[0] = preg_replace($pattern, '$1', $tmp[0]);
    14.         $tmp[1] = preg_replace($pattern, '$1', $tmp[1]);
    15.        
    16.         $data[$tmp[0]] = $tmp[1];
    17.     }
    18.    
    19.     return $data;
    20. }
    21.  
    и это будет надстройка к шаблонизатору, для того, что бы из шаблонов можно было вызывать объекты
     
  16. Ti

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

    С нами с:
    3 июл 2006
    Сообщения:
    2.378
    Симпатии:
    1
    Адрес:
    d1.ru, Екатеринбург
    проще подогнать под JSON формат и заюзать json_decode

    пробелы не имеют значения, кавычки можно заменить.

    PHP:
    1. <?
    2. $result = (array) json_decode('{
    3.     "template"   : "/goodsViev.htm",
    4.     "show"   : "yes"
    5. }');

     
  17. Koc

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

    С нами с:
    3 мар 2008
    Сообщения:
    2.253
    Симпатии:
    0
    Адрес:
    \Ukraine\Dnepropetrovsk
    Ti
    тю, а я думал, что пробелы имеют значение, особенно учитывая тот факт, что ребята в комментах к этой ф-ции пишут свои ф-ции, с урезанием пробелов. Ну да черт с этим json_decode, Cherry предложил ваще офигеннейшую регулярку.

    PHP:
    1. <?
    2. private static function unparseSettings($settings)
    3. {
    4.     preg_match_all("#(\'|\")(.*)\\1\s*:\s*(\'|\")(.*)\\3#U", $settings, $matches);
    5.     return (sizeof($matches[2])) ? array_combine($matches[2], $matches[4]) : array();
    6. }
    7.