我有以下要求;
我有以下数据样本;
{
"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()
的深度。它不是要改变深度的执行。
我该如何解决这个问题?
注意:我需要有效的解决方案。我的项目需要高性能
答案 0 :(得分:2)
如果您不想使用json_decode
,可以尝试使用正则表达式提取“不要解码”字段,然后json_decode
修改后的变量,最后重新分配提取的项目进入结果数组。
regexp /"reportFields"\s*:\s*(.*)}\s*}\s*$/ms
应匹配该项并返回较低级别的数组元素。将整个匹配项替换为"reportFields": "" } }
,您将获得一个可以解码和重新丰富的JSON实体。
或者,您可以将“aras”,2和5提取为具有相同preg_match
的独立字符串,而不是preg_replace
或json_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%,而方式更简单,更易于维护。