我的array
包含来自JSON
文件的大量数据,使用json_decode
,我希望使用foreach
循环数据。
示例
$json = file_get_contents('data.json');
$data = json_decode(preg_replace('/(\])\](\R)\[/', '$1,$2', $json));
现在我只是为了逐个获取数据
foreach($data as $d){
...
}
但是foreach似乎有限,它没有给我文件的所有数据,但只有其中的一些,我不明白为什么,任何想法为什么以及如何解决这个问题?
原始字符串:(无效的JSON) https://paste.ee/r/RN7rK
修改后的结构和json_decode
结果 (using print_r)
:我无法发布,它太大,请尝试我的preg_replace
,然后{{1} }
答案 0 :(得分:1)
您的JSON解码数组中有7516条记录。
此记录集有两个不同的部分:
6970条记录的第一部分包含22个元素的记录,第一部分的值为“s”。第一次出现是这样的:
["s","13","shelves_norja","49500","0","1","1","#ffffff,#F7EBBC",
"Beige Bookcase", "For nic naks and books.","","5", "true", "-1",
"false","","1","true","0","0","0","false"]
546的第二部分包含19个元素的记录,第一部分的值为“i”。第一次出现:
["i","1", "post.it", "0", "", "", "", "",
"Pad of stickies","Pad of stickies", "","-1","false","-1",
"false","","5","false", "false"]
我在最后一个记录的最后一个元素之前添加了空格,以突出显示差异:
第一种类型在最后一个字段之前有3个数字字段,缺少第二种记录类型。
因此,在您的代码中,您需要测试数组元素的数量,并为这三个元素提供默认值。
您可以使用以下代码实现此目的:
foreach ($data as $d){
if (count($d) == 19) {
array_splice($d, 18, 0, array("0", "0", "0"));
}
// rest of your code
}
这会将三个“缺失的”元素注入到19个元素的数组中,这样它们就可以获得与其他元素相同的结构。
或者,你可以做相反的事情,并从较长的数组值中删除这三个元素,但要注意这些元素并不总是包含零,这样你就会有效地丢失信息。 / p>
但是,正如您在评论中所说,您缺少大约7000条记录,这表明您在处理较长的阵列时遇到问题。如果您想使用此替代方案,您的代码将变为:
foreach ($data as $d){
if (count($d) == 22) {
array_splice($d, 18, 3);
}
// rest of your code
}
答案 1 :(得分:0)
执行此测试的记录为7516:
/* My original json manipulation: */ # 01
if( 1 )
{
$json = preg_replace('/[\n\r\t]/','',$json);
$json = str_replace( '][', '],[', $json );
$json = preg_replace( '/\[\[+/', '[', $json );
$json = preg_replace( '/\]\]+/', ']', $json );
$json = "[$json]";
}
/* Your original json manipulation: */
else
{
$json = preg_replace('/(\])\](\R)\[/', '$1,$2', $json);
}
$data = json_decode( $json ); # 02
/* Inverse test: */
$lost = 0;
foreach( $data as $row )
{
$enc = json_encode( $row );
if( FALSE===strpos( $json, $enc ) ) $lost++; # 03
else $json = str_replace( $enc, '', $json );
}
$json = preg_replace('/],,+\[/','],[',$json); # 04
$found = explode( '],[',$json );
echo "Total: ".count($data).PHP_EOL;
echo "Lost: $lost".PHP_EOL;
echo "Found: ".count($found).PHP_EOL;
在步骤#01 ,您可以找到我的json操作。它可以缩短,但为了清楚起见我留下了它。您可以将if( 1 )
更改为if( 0 )
以应用正则表达式。
在json解码(#02 )之后,我执行了一个反向测试:我处理每个解码后的数组值,在json中重新编码它并搜索它们是否存在于json字符串中(# 03 ):如果它们存在,我会从json字符串中删除它,否则我会增加$lost
变量。
在foreach
循环之后,我在转换后的json字符串中减少多次出现,
,然后在数组中将其],[
拆分。
最后,我打印解码的json中的项目总数,丢失的项目总数和修改后的json的总行数。 使用我的操作,结果是'Lost:65,Found:65',使用你的操作结果是'Lost:65,Found:45'(但我没有重新编辑最终的json转换)。< / p>
鉴于Lost / Found的数量是相同的,我认为很可能没有元素保持未解码,但如果你想要,你可以执行更准确的检查,将$lost
声明为数组,然后,在#03 ,以这种方式更改行:
if( FALSE===strpos( $json, $enc ) ) $lost[] = $enc;
然后,在foreach
循环结束时:
(...)
$found = explode( '],[',$json );
print_r( $lost );
print_r( $found );
然后手动检查是否每个未找到的项目在剩余的修改过的json中都有相应的值。
PS:由于编码特殊字符问题,它们是“丢失”的记录。