簡體   English   中英

PHP | json_decode巨大的json文件

[英]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_decodefile_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM