2009-10-15 41 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) 
}