将解析JSON输出转换为CSV(逗号分隔值)格式处理大型数据集

4
Parse允许用户使用其“导出”工具下载数据,但只允许以JSON格式导出数据。我想将其转换为CSV格式以在Excel中进行分析。
对于较小的JSON对象,简单的脚本就足够了,但我处理的数据集有670,000行,超过360MB。在线转换器无法处理此文件大小,经常引用PHP已超出其内存限制。
我尝试过基于PHP CLI的脚本和在线转换器,但它们似乎都超出了其分配的内存。当ini_set('memory_limit', '4096M');仍然没有给我足够的内存时,我意识到我需要一种新的方法。
我目前正在使用这个基于CLI的脚本来解析数据:
// flatten to CSV
function flatten2CSV($file){
    $fileIO = fopen($file, 'w+');
    foreach ($this->dataArray as $items) {
        $flatData = array();
        $fields = new RecursiveIteratorIterator(new RecursiveArrayIterator($items));
        foreach($fields as $value) {
            array_push($flatData, $value);
        }
        fputcsv($fileIO, $flatData, ";", '"');
    }
    fclose($fileIO);
}

// and $this->dataArray is created here
function readJSON($JSONdata){
    $this->dataArray = json_decode($JSONdata,1);
    $this->prependColumnNames();
    return $this->dataArray;
}

private function prependColumnNames(){
    foreach(array_keys($this->dataArray[0]) as $key){
        $keys[0][$key] = $key;
    }
    $this->dataArray = array_merge($keys, $this->dataArray);
}

如何解决使用PHP处理大型数据集时的内存管理问题?有没有比使用json_decode更好的读取JSON对象的方法?


您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Eric G
可以将数据从Parse中导出为较小的数据集,但是对于定期从数据库中提取数据来说,这变得耗时。我已经添加了我正在使用的JSON2CSV类来解析JSON。 - Adam Link
我不熟悉Parse。你能否编写一个脚本来下载较小的文件集?此外,如果您在网页中运行此转换,如果您不需要在屏幕上显示输入,则这样做并没有太多意义。将其作为批处理作业在命令行上进行调度更有意义。您能否说明一下为什么要在浏览器中尝试执行此操作? - Eric G
所以Parse是一种流行的后台数据库和 API 组合,用于移动应用程序开发。我不仅想在浏览器中进行操作 - 我对将 JSON 转换为 CSV 的任何方法都持开放态度。编写脚本会产生 I/O,这很麻烦,因为 Parse 会限制 API 调用速率。 - Adam Link
3个回答

1
你可以尝试使用: https://github.com/jehiah/json2csv 转换:
{"user": {"name":"jehiah", "password": "root"}, "remote_ip": "127.0.0.1", "dt" : "[20/Aug/2010:01:12:44 -0400]"}
{"user": {"name":"jeroenjanssens", "password": "123"}, "remote_ip": "192.168.0.1", "dt" : "[20/Aug/2010:01:12:44 -0400]"}
{"user": {"name":"unknown", "password": ""}, "remote_ip": "76.216.210.0", "dt" : "[20/Aug/2010:01:12:45 -0400]"}

to:

"jehiah","127.0.0.1"
"jeroenjanssens","192.168.0.1"
"unknown","76.216.210.0"

你可能会选择
json2csv -k user.name,remote_ip -i input.json -o output.csv

1
事实证明,根据我进行的一些研究,PHP没有本地支持流式JSON解析器。然而,Salsify撰写了一篇优秀的博客文章,介绍了他们如何为PHP创建流式JSON解析器

这是GitHub代码链接

使用他们的example.php文件,我成功将JSON文件读入PHP对象。
还有一些其他的事项需要注意,才能使其正常工作:
  • Increase the memory limit for PHP: I changed the memory_limit in php.ini to read as memory_limit=2048M
  • Modify the flatten2CSV() function: My new code needed to include the Parse format for their JSON which is { "results": [ objects ] }. The new function is:

    function flatten2CSV($file, $data){     
        $fileIO = fopen($file, 'w+');
        foreach ($data['results'] as $items) {
            $flatData = array();
            $fields = new RecursiveIteratorIterator(new RecursiveArrayIterator(new RecursiveArrayIterator($items)));
            foreach($fields as $value) {
                array_push($flatData, $value);
            }
            fputcsv($fileIO, $flatData, ";", '"');
        }
        fclose($fileIO);
    }
    
  • Manually add the headers: For the purpose of this exercise, the above code was sufficient for me to parse my file. However, I did have to manually add the header line to my CSV file. I'd suggest writing code to pull out the keys and add these as headers.

使用此函数可能会因个人情况而异。由于我必须专门修改解析JSON的函数,您的JSON可能无法在其中运行。我的解析对象并不太复杂,因此指针数组可能会破坏它。


1
如果您能在浏览器中运行脚本,请查看PapaParse JavaScript库--它支持分块和多线程处理更大的数据集,并可以将JSON转换为CSV
可能相关的具体配置选项
  • worker
  • chunk
  • fastMode
或者,有一个PapaParse的Node.js分支,但没有workerchunk选项。 我与该库无关,但已成功地将其用于大型数据集上的CSV到JSON转换。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接