json_decode用于特定的执行时间深度

时间:2013-07-12 15:01:07

标签: php json

我有以下要求;

我有以下数据样本;

{
    "username" : "aras", 
    "id" : 2, 
    "report" : {
        "reportId" : 5, 
        "reportFields" : {json array}
    } 
}

我想按以下方式解码数据;

[username] => aras
[id] => 2
[report] => array(
    reportId => 5,
    reportFields => {json array} // which should be string only

我看过json_decode()的深度。它不是要改变深度的执行。

我该如何解决这个问题?

注意:我需要有效的解决方案。我的项目需要高性能

1 个答案:

答案 0 :(得分:2)

如果您不想使用json_decode,可以尝试使用正则表达式提取“不要解码”字段,然后json_decode修改后的变量,最后重新分配提取的项目进入结果数组。

regexp /"reportFields"\s*:\s*(.*)}\s*}\s*$/ms应匹配该项并返回较低级别的数组元素。将整个匹配项替换为"reportFields": "" } },您将获得一个可以解码和重新丰富的JSON实体。

或者,您可以将“aras”,2和5提取为具有相同preg_match的独立字符串,而不是preg_replacejson_decode

技术上使用regexp是 DEAD WRONG 因为JSON字典可以按任何顺序包含,而我提供的正则表达式只能识别特定字段中的字段订单 - 应该有大约12个可能的订单? - 如果订单不匹配,将会失败。

但是,通常,JSON生产者倾向于以相同的顺序提供答案。但要检查是否是这种情况。

<?php

        $json = <<<JSON {
    "username" : "aras",
    "id" : 2,
    "report" : {
        "reportId" : 5,
        "reportFields" : {json array}
    } } JSON;
        preg_match('#^\\s*{\\s*"username"\\s*:\\s*"(.*?)",\\s*'
                   .'"id"\\s*:\\s*(\d+),\\s*'
                   .'"report"\\s*:\\s{\\s*"reportId"\\s*:\\s*(\d+),'
                   .'\\s*"reportFields"\\s*:\\s*{(.*?)}\\s*}\\s*}\\s*$#sm',
                        $json,
                        $gregs);
   $ar = array( 'username' => $gregs[1],
                 'id' => $gregs[2],
                 'report' => array(
                   'reportId' => $gregs[3],
                   'reportFields' => $gregs[4] ));

    print_r($ar);

输出:

Array
(
    [username] => aras
    [id] => 2
    [report] => Array
        (
            [reportId] => 5
            [reportFields] => json array
        )

)

注意

根据json_array的大小和结构,“递归解码,然后重新编码$ar['report']['reportFields']”解决方案可能更具性能(除了更易于维护):

$ar = json_decode($json);
$ar['report']['reportFields'] = json_encode($ar['report']['reportFields']);

如果json_array不太复杂,我会避免使用正则表达式解决方案。

测试性能

显然,regexp解决方案(实际上)的速度绝不会超过JSON解决方案的两倍。

所以,如果regexp有可能维护(即JSON格式可能会改变),我肯定使用JSON版本。

<?php

        $z = array('test');

        for ($items = 1; $items < 100; $items++)
        {
                $z[]    = "test-$items";
                $j      = json_encode($z);

                $json = <<<JSON
{
    "username" : "aras",
    "id" : 2,
    "report" : {
        "reportId" : 5,
        "reportFields" : $j
    }
}
JSON;
                if ($items % 10)
                        continue;

                $ITER = 100000;
                $a = microtime(True);
                for ($i = 0; $i < $ITER; $i++) {
                        preg_match('#^\\s*{\\s*"username"\\s*:\\s*"(.*?)",\\s*'
                                   .'"id"\\s*:\\s*(\d+),\\s*'
                                   .'"report"\\s*:\\s{\\s*"reportId"\\s*:\\s*(\d+),'
                                   .'\\s*"reportFields"\\s*:\\s*([[].*?[]])\\s*}\\s*}\\s*$#sm',
                                        $json,
                                        $gregs);
                        $ar = array( 'username' => $gregs[1],
                                     'id' => $gregs[2],
                                     'report' => array( 'reportId' => $gregs[3], 'reportFields' => $gregs[4] ));
                }
                $b = microtime(True);
                for ($i = 0; $i < $ITER; $i++) {
                        $ar = json_decode($json, True);
                        $ar['report']['reportFields'] = json_encode($ar['report']['reportFields']);
                }
                $c = microtime(True);
                $s1 = number_format(1000000*($b-$a)/$ITER, 2);
                $s2 = number_format(1000000*($c-$b)/$ITER, 2);
                $r  = $s1/$s2;
                print "$items items, regexp: $s1 million op/s, JSON: $s2 million op/s, ratio=$r\n";
        }
?>

输出(部分):

10 items, regexp: 6.65 million op/s, JSON: 8.25 million op/s, ratio=0.806060606060606144
20 items, regexp: 8.47 million op/s, JSON: 12.00 million op/s, ratio=0.705833333333333424
30 items, regexp: 9.93 million op/s, JSON: 15.54 million op/s, ratio=0.638996138996139051
40 items, regexp: 11.85 million op/s, JSON: 19.11 million op/s, ratio=0.620094191522762905
50 items, regexp: 13.46 million op/s, JSON: 22.68 million op/s, ratio=0.593474426807760191
60 items, regexp: 15.18 million op/s, JSON: 26.74 million op/s, ratio=0.567688855646970802
70 items, regexp: 16.85 million op/s, JSON: 30.35 million op/s, ratio=0.555189456342668919

正则表达式解决方案可以更好地扩展,但需要相当长的json_array才能使其几乎两倍于JSON解决方案。对于典型的短输入,JSON解决方案的速度是正则表达式的80%,而方式更简单,更易于维护。