2015-02-27 3 views
0

Я использую PHP на общем сервере для доступа к внешнему сайту через API, который возвращает JSON, содержащий 2 уровня данных (Уровень 1: Исполнитель & Уровень 2: Внутренний элемент категории). Я хочу, чтобы преобразовать это многомерный ассоциативный массив без применения функции json_decode (она использует слишком много памяти для такого использования !!!)Преобразование строки JSON в массив WITHOUT json_decode

Примера данных JSON:

[ 
{ 
    "performerId": 99999, 
    "name": " Any performer name", 
    "category": { 
     "categoryId": 99, 
     "name": "Some category name", 
     "eventType": "Category Event" 
    }, 
    "eventType": "Performer Event", 
    "url": "http://www.novalidsite.com/something/performerspage.html", 
    "priority": 0 
}, 
{ 
    "performerId": 88888, 
    "name": " Second performer name", 
    "category": { 
     "categoryId": 88, 
     "name": "Second Category name", 
     "eventType": "Category Event 2" 
    }, 
    "eventType": "Performer Event 2", 
    "url": "http://www.novalidsite.com/somethingelse/performerspage2.html", 
    "priority": 7 
} 
] 

Я пытался использовать SUBSTR и полосу «[» и «]».

Затем выполняется вызов:

preg_match_all('/\{([^}]+)\}/', $input, $matches); 

Это дает мне строку для каждой строки НО обрезает после завершающего «}» из данных категорий.

Как я могу вернуть FULL ROW данных AS ARRAY, используя что-то вроде preg_split, preg_match_all и т. Д. ВМЕСТО из тяжелых вызовов, таких как json_decode, в общую строку JSON?

Как только у меня есть массив с каждой правильно обозначенной строкой, я МОГУТ, ЧТО выполнить json_decode в этой строке, не перегружая память на общем сервере.


Для тех, кто хочет более подробно об использовании json_decode вызывает ошибки:

$aryPerformersfile[ ] = file_get_contents('https://subdomain.domain.com/dir/getresults?id=1234'); 
$aryPerformers = $aryPerformersfile[0]; 
unset($aryPerformersfile); 
$mytmpvar = json_decode($aryPerformers); 
print_r($mytmpvar); 
exit; 
+1

Может ли эта ссылка http://stackoverflow.com/que stions/2583472/regex-to-validate-json будут полезны? – crrad

+1

Таким образом, вместо использования json_decode вы вместо этого вызываете, несомненно, менее эффективное обходное решение. Ага. Это будет плавно. @AbraCadaver проверить [phantomJS] (http://phantomjs.org/) –

+0

как он использует слишком много памяти? можете ли вы показать нам, как его слишком много использовать, каково ваше определение слишком много? моя догадка заключается не в том, что функция использует много, а в том, что ваш мусор не собирает правильно с 'unset()', или вам нужно увеличить выделение памяти в вашем приложении. – cmorrissey

ответ

3

Если у вас ограниченный объем памяти, вы можете прочитать данные как поток и разобрать JSON за один раз за раз, вместо того, чтобы разобрать все сразу.

getresults.JSON:

[ 
    { 
     "performerId": 99999, 
     "name": " Any performer name", 
     "category": { 
      "categoryId": 99, 
      "name": "Some category name", 
      "eventType": "Category Event" 
     }, 
     "eventType": "Performer Event", 
     "url": "http://www.novalidsite.com/something/performerspage.html", 
     "priority": 0 
    }, 
    { 
     "performerId": 88888, 
     "name": " Second performer name", 
     "category": { 
      "categoryId": 88, 
      "name": "Second Category name", 
      "eventType": "Category Event 2" 
     }, 
     "eventType": "Performer Event 2", 
     "url": "http://www.novalidsite.com/somethingelse/performerspage2.html", 
     "priority": 7 
    } 
] 

PHP:

$stream = fopen('getresults.json', 'rb'); 

// Read one character at a time from $stream until 
// $count number of $char characters is read 
function readUpTo($stream, $char, $count) 
{ 
    $str = ''; 
    $foundCount = 0; 
    while (!feof($stream)) { 
     $readChar = stream_get_contents($stream, 1); 

     $str .= $readChar; 
     if ($readChar == $char && ++$foundCount == $count) 
      return $str; 
    } 
    return false; 
} 

// Read one JSON performer object 
function readOneJsonPerformer($stream) 
{ 
    if ($json = readUpTo($stream, '{', 1)) 
     return '{' . readUpTo($stream, '}', 2); 
    return false; 
} 

while ($json = readOneJsonPerformer($stream)) { 
    $performer = json_decode($json); 

    echo 'Performer with ID ' . $performer->performerId 
     . ' has category ' . $performer->category->name, PHP_EOL; 
} 
fclose($stream); 

Выход:

Performer with ID 99999 has category Some category name 
Performer with ID 88888 has category Second Category name 

Этот код, конечно, может быть улучшена за счет использования буфера для более быстрого чтения, примите во внимание, что строковые значения могут сами включают { и } символы и т. д.

+0

Спасибо @mhall! высоко оценил –

+1

Это помогло мне получить тонну. Благодаря! Для других, используя это, обязательно настройте параметр $ count в зависимости от количества закрывающих скобок, с которыми вы работаете. –

0

У вас есть два варианта здесь, и ни один из них включают в себя вы пишете свой собственный декодер; не слишком усложняйте решение с помощью ненужной работы.

1) Уменьшите размер json, который декодируется, или 2) Увеличьте допустимую память на своем сервере.

Первый вариант требует доступа к создаваемому json. Это может быть или не быть возможным в зависимости от того, является ли вы тем, кто изначально создавал json. Самый простой способ сделать это - unset() любые бесполезные данные. Например, может быть, есть некоторая информация об отладочной информации, которая вам не понадобится, поэтому вы можете сделать unset($json_array['debug']); по бесполезным данным. http://php.net/manual/en/function.unset.php

Второй вариант требует наличия у вас доступа к файлу php.ini на вашем сервере. Вам нужно найти линию с чем-то вроде memory_limit = 128M и сделать часть 128M более крупной. Попробуйте увеличить это, чтобы удвоить значение уже в файле (таким образом, в этом случае это будет 256M). Это может не решить вашу проблему, поскольку большие данные json все еще могут быть ядром вашей проблемы; это только обеспечивает работу для неэффективного кода.

+1

Также стоит отметить, что проблема может быть не связана с данными json. Проблема может быть вызвана большой переменной, которая может быть вызвана до того, как декодирование когда-либо произойдет, и в этом случае декодирует «солому, которая сломала спину верблюда». – Siphon

Смежные вопросы