如果您不想使用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%,而且更简单、更易于维护。