Я вытаскиваю 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()
в этой строке. Он ничего не возвращает.
"
а не одинарные кавычки '
. 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) }