2009-10-15 71 views
3

我正在拉取JSON無效的JSON供稿。它完全缺少引號。我已經嘗試了一些東西,比如explode()str_replace(),以使字符串看起來更像是有效的JSON,但是在關聯JSON字符串的情況下,它通常會搞砸。使用PHP的JSON解析無效

下面是一個例子:

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

是否有任何PHP解析器JSON在那裏,可以處理無效的JSON這樣嗎?

編輯:我試圖在這個字符串上使用json_decode()。它什麼都不返回。

+1

我不相信數字在JSON中需要引號 – 2009-10-15 21:31:46

+0

但是「鍵」確實是,不是嗎?像id:43015應該是「id」:43015,對吧? – hookedonwinter 2009-10-15 21:37:50

+0

是的,問題是沒有引用像「id」這樣的密鑰名稱 – 2009-10-15 21:39:25

回答

10
  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)); 
    } 
+0

奇妙的工作!感謝Marko。 – hookedonwinter 2009-10-15 22:04:12

+0

嘗試將值設置爲URL或其中包含冒號的值。這不起作用。 (即id:43015,name:'http:John Doe',lev ...) – KXL 2014-10-05 23:04:42

0

我想說你最好的選擇是下載一個JSON解碼器的源代碼(它們並不是很大)並且擺弄它,特別是如果你知道你想解碼的JSON有什麼問題。

您提供的示例也需要{},這可能會有所幫助。

4

從我的經驗馬爾科的回答不工作了。對於較新的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); 
+0

支持數組: $ a = preg_replace('/(,| \ {)[\ t \ n] *(\ w + )[] *:[] * /','$ 1「$ 2」:',$ a); $'$'$,$'$'$,$ a $'$'$,'$'$,'$'$,$'$'$,'$' ; $ a = preg_replace('/「:\'?\」?([^ \ [\] \ {\}] *?)\'?\「?[\ n \ t] *(,」| \} $ | \] $ | \} \] | \] \} | \} | \])/ '' 「:」 $ 1" $ 2' ,$ a)的 – 2013-05-22 17:34:57

3

此正則表達式會做的伎倆

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

該解決方案似乎是足以讓最常見的用途。

0

我知道這個問題很老,但我希望這可以幫助別人。

我有一個類似的問題,因爲我想接受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) 
}