python - 将巨大的 JSON 文件流式解析为小文件

标签 python json stream jq

我有大约 96 gzip 的 JSON,使用以下结构解压缩后,这是超过 350 GB 的 JSON 文件

{
  "structe": {},
  "beta": {},
  "flow": {
    "1023": {
      "0101": {
        "-LEjllNyHqdHYGntO6vu": {
          "status": "1",
          "t": 1528736191996
        },
        "-LEjllcXKaVOQu3BDpHF": {
          "status": "1",
          "t": 1528736192996
        }
      },
      "0102": {
        "-LEjllNyHqdHYGntO6vu": {
          "status": "1",
          "t": 1528736191996
        },
        "-LEjllcXKaVOQu3BDpHF": {
          "status": "1",
          "t": 1528736192996
        }
      }
    },
    "1024": {
      "0103": {
        "-LEjllNyHqdHYGntO6vu": {
          "lat": 51.128676733981,
          "lng": -113.9318991267252,
          "status": "1",
          "t": 1528736191996
        },
        "-LEjllcXKaVOQu3BDpHF": {
          "lat": 51.128676733981,
          "lng": -113.9318991267252,
          "status": "1",
          "t": 1528736192996
        }
      }
    }
  }
}

我无法将其加载到 RAM 中,现在我想流式传输此文件并将路径 flow->1023(let id1)->0101(let id2) 拉入新的 id1_id2.json 文件。任何想法如何能够快速做到这一点。 我正在寻找的输出就像 文件名=1023_0101.json

{
        "-LEjllNyHqdHYGntO6vu": {
          "status": "1",
          "t": 1528736191996
        },
        "-LEjllcXKaVOQu3BDpHF": {
          "status": "1",
          "t": 1528736192996
        }
      }

最佳答案

这里有一个解决方案,使用 jq 的流解析器来生成一个由 $id1、$id2 和相应的感兴趣值组成的流;然后可以将该流传输到另一个工具(例如 awk,如果方便的话)以生成所需的文件。

下面,我们使用 jq Cookbook 中的 atomize:

  def atomize(s):
    fromstream(foreach s as $in ( {previous:null, emit: null};
      if ($in | length == 2) and ($in|.[0][0]) != .previous and .previous != null
      then {emit: [[.previous]], previous: $in|.[0][0]}
      else { previous: ($in|.[0][0]), emit: null}
      end;
      (.emit // empty), $in) ) ;

主 jq 程序(使用 --stream -n -c 调用)很简单:

atomize(inputs)
| select(type == "object" and .flow)
| .flow
| keys_unsorted[] as $id1
| (.[$id1] | keys_unsorted[]) as $id2
| $id1, $id2, .[$id1][$id2]

因此,对于每个 gzip 文件 $gz,管道将如下所示:

gunzip -c $gz | jq -nc --stream -f 程序.jq | awk ....

有关使用 awk 生成所需结果的示例,请参阅 jq, split a huge json of array and save into file named with a value

注意事项和附录

jq 的流解析器避免以速度为代价使用 RAM,因此通常使用 --stream 选项只是作为最后的手段。从问题的描述来看,您似乎可以使用 jq 的常规解析器处理一些压缩文件,因此您可能希望快速处理这些文件,而对那些太大的文件保留“原子化”方法。

注意

问题描述没有明确如果出现 id1_id2.json 冲突该怎么办。如果没有这种碰撞的可能,那当然就没有问题。否则,将由创建这些文件的程序来管理该意外情况。

关于python - 将巨大的 JSON 文件流式解析为小文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58408121/

相关文章:

python - 属性错误 : 'module' object has no attribute 'get_frontal_face_detector'

json - 为什么不是来自 ambari 集群的所有参数都不由蓝图 json 文件表示

ios - 无法通过下拉刷新 tableview Controller 中的刷新我的 JSON 数据

php - PHP 中是否可以确定文件描述符的状态?

python - 监听多个网络上的多播流量

python - 无法使用 python 社交身份验证设置自定义参数

python - Django - 为开发 Web 服务器显示 404 页面 (http ://127. 0.0.1:8000/)

javascript - 通过 JSON 传递给 JavaScript 之前在哪里声明 PHP?

python - 在 Python 的同一进程中捕获标准输出

java - 尝试从公共(public)流读取时出现错误 403