确定包含单个 JSON 实体的非常大的文件的结构的一种通用方法是运行以下查询:
jq -nc --stream -f structural-paths.jq huge.json | sort -u
where structural_paths.jq
包含:
inputs
| select(length == 2)
| .[0]
| map( if type == "number" then 0 else . end )
请注意,输出中的“0”表示相应位置至少有一个有效的数组索引,而不是“0”实际上是该位置的有效索引。
另请注意,对于非常大的文件,使用 jq --stream 处理整个文件可能会非常慢。
Example:
Given {"a": {"b": [0,1, {"c":2}]}}
,上述咒语的结果将是:
["a","b",0,"c"]
["a","b",0]
顶层结构
如果您只想了解有关顶层结构的更多信息,您可以将上面的 jq 程序简化为:
inputs | select(length==1)[0][0] | if type == "number" then 0 else . end
给定深度的结构
如果命令行sort
失败,那么您可能希望通过仅将路径考虑到一定深度来限制路径数量。
如果深度不是太大,那么希望你的命令行sort
将能够管理;如果没有,则使用命令行uniq
至少会稍微削减输出。
更好的选择可能是定义unique(stream)
在 jq 中,然后使用它,如下所示:
# Output: a stream of the distinct `tostring` values of the items in the stream
def uniques(stream):
foreach (stream|tostring) as $s ({};
if .[$s] then .emit = false else .emit = true | .item = $s | .[$s]=true end;
if .emit then .item else empty end );
def spaths($depth):
inputs
| select(length==1)[0][0:$depth]
| map(if type == "number" then 0 else . end);
uniques(spaths($depth))
jq 的合适调用如下所示:
jq -nr --argjson depth 3 --stream -f structural-paths.jq huge.json
除了避免分类成本之外,还可以使用uniques/1
将保留原始 JSON 中路径的顺序。
“JSON 指针”指针
如果您想将数组路径表达式转换为“JSON Pointer”字符串(例如与jm
or jstream
),只需将以下内容附加到相关的 jq 程序中:
| "/" + join("/")