1

我有以下要求;

我有以下数据样本;

{
    "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()' 的深度。这与改变深度的执行无关。

我该如何解决这个问题?

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

4

1 回答 1

2

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

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

或者,您可以将“aras”、2 和 5 提取为具有相同preg_match且不运行preg_replace或根本不运行的独立字符串json_decode

从技术上讲,使用正则表达式是完全错误的,因为 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不是太复杂,我会避免使用正则表达式解决方案。

测试性能

显然,正则表达式解决方案(在实践中)最多不会比 JSON 解决方案快两倍。

因此,如果有可能必须维护正则表达式(即 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

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

于 2013-07-12T15:15:19.557 回答