2016-06-17 64 views
4

即時通訊試圖解碼大型json文件222mb文件。PHP | json_decode巨大的json文件

我明白我不能直接使用的file_get_contents()讀取整個文件和解碼整個字符串使用json_decode,因爲它會消耗很多的內存,並會返回任何結果(這是到目前爲止什麼它做什麼。)

所以我去試試圖書館, 我最近嘗試的是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數組的所有對象執行此操作,但問題是如何使用此庫循環它,或者不存在此類選項。

或者是其他更好的選擇或圖書館這種工作?

+0

你不應該爲你想要的使用循環。解析器只會發出你的回調應該處理的事件,並且做他們想要/需要處理的數據。或者有https://github.com/salsify/jsonstreamingparser。我不能擔保任何一個圖書館,所以你必須自己檢查一下。 – PeeHaa

回答

-5

您仍然需要使用json_decodefile_get_contents才能獲得完整的JSON(您無法解析部分JSON)。剛開始使用ini_set('memory_limit', '500M');

而且您要處理不再那麼這裏使用set_time_limit(0);

+0

不知道upvote來自哪裏,但這個答案根本不是這樣。 – PeeHaa

+0

我已經使用過'ini_set('memory_limit','-1');'但是會使用你建議的時間限制。 但我問的問題是,如何循環?我知道我必須使用json_decode。我也知道我知道我無法使用完整的文件。它只能用於塊等。是的,你的回答是不正確的。我們可以解析部分json。有這樣的圖書館。 –

+0

@PeeHaa - 爲什麼這個答案不正確?我在這裏閱讀,我真的很想知道爲什麼。我是否應該心靈感應地閱讀你的思想,還是應該盲目地相信你的陳述而沒有證據或反駁? –

4

一種替代增加內存限制的PHP更大的價值是使用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; 
} 

爲了讓事情簡單地理解,我的「M使用此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文件和它的作品。也許你需要讓聽衆適應你的需求。

+0

使用「Guzzle,PHP HTTP客戶端」從url下載json而不加載到內存。 – ram4nd

+0

一個問題,爲什麼是「$ this-> insertValue($ obj ['value']);」需要。它只會增加內存使用量?如果您不需要全部輸出,您可以剝離它嗎? – ram4nd