Недопустимый синтаксический анализ JSON с использованием PHP

Я вытаскиваю JSON-канал, который недействителен JSON. Котировки полностью отсутствуют. Я пробовал несколько вещей, таких как str_replace() explode() и str_replace() , чтобы строка выглядела немного больше, чем действительный JSON, но внутри сотовой строки JSON внутри она обычно прикручивается.

Вот пример:

 id:43015,name:'John Doe',level:15,systems:[{t:6,glr:1242,n:'server',s:185,c:9}],classs:0,subclass:5 

Существуют ли какие-либо парсеры JSON для php, которые могут обрабатывать недействительный JSON?

Изменить: Я пытаюсь использовать json_decode() в этой строке. Он ничего не возвращает.

  1. Все кавычки должны быть двойными кавычками " а не одинарные кавычки ' .
  2. Все ключи должны быть указаны.
  3. Весь элемент должен быть объектом.
     function my_json_decode ($ s) {
         $ s = str_replace (
             array ('' ',' ''),
             array ('\ "', '' '),
             $ s
         );
         $ s = preg_replace ('/ (\ w +): / i', '"\ 1":', $ s);
         return json_decode (sprintf ('{% s}', $ s));
     }

По моему опыту, ответ Марко больше не работает. Для новых версий PHP используйте istead:

 $a = "{id:43015,name:'John Doe',level:15,systems:[{t:6,glr:1242,n:'server',s:185,c:988}],classs:0,subclass:5}"; $a = preg_replace('/(,|\{)[ \t\n]*(\w+)[ ]*:[ ]*/','$1"$2":',$a); $a = preg_replace('/":\'?([^\[\]\{\}]*?)\'?[ \n\t]*(,"|\}$|\]$|\}\]|\]\}|\}|\])/','":"$1"$2',$a); print_r($a); 

Это регулярное выражение сделает трюк

 $json = preg_replace('/([{,])(\s*)([A-Za-z0-9_\-]+?)\s*:/','$1"$3":',$json); 

Я бы сказал, что лучше всего скачать источник JSON-декодера (они не огромные) и с этим поиграть, особенно если вы знаете, что не так с JSON, который вы пытаетесь декодировать.

Пример, который вам предоставил, {} вокруг него тоже может помочь.

 $json = preg_replace('/([{,])(\s*)([A-Za-z0-9_\-]+?)\s*:/','$1"$3":',$json);// adding->(") $json = str_replace("'",'"', $json);// replacing->(') 

Этого решения, по-видимому, достаточно для большинства общих целей.

Я знаю, что этот вопрос старый, но я надеюсь, что это поможет кому-то.

У меня была аналогичная проблема, поскольку я хотел принять JSON как пользовательский ввод, но не хотел требовать утомительных «кавычек» вокруг каждого ключа. Кроме того, я не хотел требовать котировки вокруг значений, но все равно разбирать действительные числа.

Самый простой способ – написать собственный парсер.

Я придумал это, которое анализирует вложенные ассоциативные / индексированные массивы:

 function loose_json_decode($json) { $rgxjson = '%((?:\{[^\{\}\[\]]*\})|(?:\[[^\{\}\[\]]*\]))%'; $rgxstr = '%("(?:[^"\\\\]*|\\\\\\\\|\\\\"|\\\\)*"|\'(?:[^\'\\\\]*|\\\\\\\\|\\\\\'|\\\\)*\')%'; $rgxnum = '%^\s*([+-]?(\d+(\.\d*)?|\d*\.\d+)(e[+-]?\d+)?|0x[0-9a-f]+)\s*$%i'; $rgxchr1 = '%^'.chr(1).'\\d+'.chr(1).'$%'; $rgxchr2 = '%^'.chr(2).'\\d+'.chr(2).'$%'; $chrs = array(chr(2),chr(1)); $escs = array(chr(2).chr(2),chr(2).chr(1)); $nodes = array(); $strings = array(); # escape use of chr(1) $json = str_replace($chrs,$escs,$json); # parse out existing strings $pieces = preg_split($rgxstr,$json,-1,PREG_SPLIT_DELIM_CAPTURE); for($i=1;$i<count($pieces);$i+=2) { $strings []= str_replace($escs,$chrs,str_replace(array('\\\\','\\\'','\\"'),array('\\','\'','"'),substr($pieces[$i],1,-1))); $pieces[$i] = chr(2) . (count($strings)-1) . chr(2); } $json = implode($pieces); # parse json while(1) { $pieces = preg_split($rgxjson,$json,-1,PREG_SPLIT_DELIM_CAPTURE); for($i=1;$i<count($pieces);$i+=2) { $nodes []= $pieces[$i]; $pieces[$i] = chr(1) . (count($nodes)-1) . chr(1); } $json = implode($pieces); if(!preg_match($rgxjson,$json)) break; } # build associative array for($i=0,$l=count($nodes);$i<$l;$i++) { $obj = explode(',',substr($nodes[$i],1,-1)); $arr = $nodes[$i][0] == '['; if($arr) { for($j=0;$j<count($obj);$j++) { if(preg_match($rgxchr1,$obj[$j])) $obj[$j] = $nodes[+substr($obj[$j],1,-1)]; else if(preg_match($rgxchr2,$obj[$j])) $obj[$j] = $strings[+substr($obj[$j],1,-1)]; else if(preg_match($rgxnum,$obj[$j])) $obj[$j] = +trim($obj[$j]); else $obj[$j] = trim(str_replace($escs,$chrs,$obj[$j])); } $nodes[$i] = $obj; } else { $data = array(); for($j=0;$j<count($obj);$j++) { $kv = explode(':',$obj[$j],2); if(preg_match($rgxchr1,$kv[0])) $kv[0] = $nodes[+substr($kv[0],1,-1)]; else if(preg_match($rgxchr2,$kv[0])) $kv[0] = $strings[+substr($kv[0],1,-1)]; else if(preg_match($rgxnum,$kv[0])) $kv[0] = +trim($kv[0]); else $kv[0] = trim(str_replace($escs,$chrs,$kv[0])); if(preg_match($rgxchr1,$kv[1])) $kv[1] = $nodes[+substr($kv[1],1,-1)]; else if(preg_match($rgxchr2,$kv[1])) $kv[1] = $strings[+substr($kv[1],1,-1)]; else if(preg_match($rgxnum,$kv[1])) $kv[1] = +trim($kv[1]); else $kv[1] = trim(str_replace($escs,$chrs,$kv[1])); $data[$kv[0]] = $kv[1]; } $nodes[$i] = $data; } } return $nodes[count($nodes)-1]; } 

Обратите внимание, что он не улавливает ошибки или плохое форматирование …

Для вашей ситуации кажется, что вы хотите добавить {} вокруг него (как и требует json_decode ):

 $data = loose_json_decode('{' . $json . '}'); 

который для меня дает:

 array(6) { ["id"]=> int(43015) ["name"]=> string(8) "John Doe" ["level"]=> int(15) ["systems"]=> array(1) { [0]=> array(5) { ["t"]=> int(6) ["glr"]=> int(1242) ["n"]=> string(6) "server" ["s"]=> int(185) ["c"]=> int(9) } } ["classs"]=> int(0) ["subclass"]=> int(5) }