[英]PHP | json_decode huge json file
我試圖解碼大型json文件222mb文件。
我明白我不能直接使用json_decode來使用file_get_contents()來讀取整個文件並解碼整個字符串,因為它會占用大量內存並且不會返回任何內容(這就是它到目前為止所做的事情。)
所以我去嘗試庫,我最近嘗試過的是JSONParser 。 它做的是在json數組中逐個讀取對象。
但是由於那里沒有文檔,我想在這里詢問是否有人使用過這個庫。
這是來自github的示例測試代碼
// initialise the parser object
$parser = new JSONParser();
// sets the callbacks
$parser->setArrayHandlers('arrayStart', 'arrayEnd');
$parser->setObjectHandlers('objStart', 'objEnd');
$parser->setPropertyHandler('property');
$parser->setScalarHandler('scalar');
/*
echo "Parsing top level object document...\n";
// parse the document
$parser->parseDocument(__DIR__ . '/data.json');*/
$parser->initialise();
//echo "Parsing top level array document...\n";
// parse the top level array
$parser->parseDocument(__DIR__ . '/array.json');
如何使用循環並將對象保存在php變量中,我們可以輕松解碼到php數組以供我們進一步使用。
這將需要一些時間,因為它將逐一為json數組的所有對象執行此操作,但問題是如何使用此庫循環它,或者沒有這樣的選項。
或者是這種工作的任何其他更好的選擇或庫?
這里的一個替代方案是使用salsify/jsonstreamingparser
您需要創建自己的監聽器。
$testfile = '/path/to/file.json';
$listener = new MyListener();
$stream = fopen($testfile, 'r');
try {
$parser = new \JsonStreamingParser\Parser($stream, $listener);
$parser->parse();
fclose($stream);
} catch (Exception $e) {
fclose($stream);
throw $e;
}
為了簡單地理解,我使用這個json作為例子:
JSON輸入
{
"objects": [
{
"propertyInt": 1,
"propertyString": "string",
"propertyObject": { "key": "value" }
},
{
"propertyInt": 2,
"propertyString": "string2",
"propertyObject": { "key": "value2" }
}]
}
您需要實現自己的偵聽器。 在這種情況下,我只想獲取數組中的對象。
PHP
class MyListener extends \JsonStreamingParser\Listener\InMemoryListener
{
//control variable that allow us to know if is a child or parent object
protected $level = 0;
protected function startComplexValue($type)
{
//start complex value, increment our level
$this->level++;
parent::startComplexValue($type);
}
protected function endComplexValue()
{
//end complex value, decrement our level
$this->level--;
$obj = array_pop($this->stack);
// If the value stack is now empty, we're done parsing the document, so we can
// move the result into place so that getJson() can return it. Otherwise, we
// associate the value
if (empty($this->stack)) {
$this->result = $obj['value'];
} else {
if($obj['type'] == 'object') {
//insert value to top object, author listener way
$this->insertValue($obj['value']);
//HERE I call the custom function to do what I want
$this->insertObj($obj);
}
}
}
//custom function to do whatever
protected function insertObj($obj)
{
//parent object
if($this->level <= 2) {
echo "<pre>";
var_dump($obj);
echo "</pre>";
}
}
}
產量
array(2) {
["type"]=>
string(6) "object"
["value"]=>
array(3) {
["propertyInt"]=>
int(1)
["propertyString"]=>
string(6) "string"
["propertyObject"]=>
array(1) {
["key"]=>
string(5) "value"
}
}
}
array(2) {
["type"]=>
string(6) "object"
["value"]=>
array(3) {
["propertyInt"]=>
int(2)
["propertyString"]=>
string(7) "string2"
["propertyObject"]=>
array(1) {
["key"]=>
string(6) "value2"
}
}
}
我測試了它與166MB的JSON文件,它的工作原理。 也許你需要讓聽眾適應你的需要。
另一種選擇是使用halaxa / json-machine 。
在通過JSON迭代的情況下的用法與json_decode
情況相同,但無論文件有json_decode
,它都不會達到內存限制。 不需要實施任何東西,只需要你的foreach
。
例:
$users = \JsonMachine\JsonMachine::fromFile('500MB-users.json');
foreach ($users as $id => $user) {
// process $user as usual
}
有關詳細信息,請參閱github自述文件。
您仍然需要使用json_decode
和file_get_contents
來獲取完整的JSON(您無法解析部分JSON)。 只需使用ini_set('memory_limit', '500M');
將PHP的內存限制增加到更大的值ini_set('memory_limit', '500M');
你也將處理更長時間,所以使用set_time_limit(0);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.