将 JSON 文件拆分为单独的文件

Split a JSON file into separate files

我有一个很大的 JSON 文件,它是对象的对象,我想在对象键之后将其拆分为单独的文件名。是否可以使用 jq 或任何其他现成的工具来实现此目的?

原文JSON格式如下

{ "item1": {...}, "item2": {...}, ...}

鉴于此输入,我想生成文件 item1.json、item2.json 等

这应该给你一个开始:

for f in `cat input.json | jq -r 'keys[]'` ; do
  cat input.json | jq ".$f" > $f.json
done

或者当您坚持使用一些似乎更喜欢的更害羞的语法时:

for f in $(jq -r 'keys[]') ; do
  jq ".[\"$f\"]" < input.json > "$f.json"
done < input.json

这是一个只需要调用一次 jq 的解决方案:

jq -cr 'keys[] as $k | "\($k)\n\(.[$k])"' input.json |
  while read -r key ; do
    read -r item
    printf "%s\n" "$item" > "/tmp/$key.json"
  done

将 jq 命令的输出通过管道传输到 awk 可能会更快,例如:

jq -cr 'keys[] as $k | "\($k)\t\(.[$k])"' input.json |
  awk -F\t '{ print  > "/tmp/"  ".json" }'

当然,如果键名包含不能在文件名中使用的字符,则需要修改这些方法。

Is it possible to achieve this using jq or any other off-the-shelf tools?

是的。 也可以非常有效地做到这一点。

让我们假设 'input.json' :

{
  "item1": {
    "a": 1
  },
  "item2": {
    "b": 2
  },
  "item3": {
    "c": 3
  }
}

低效Bash方法:

for f in $(xidel -s input.json -e '$json()'); do
  xidel -s input.json -e '$json("'$f'")' > $f.json
done

对于每个对象键,都会调用另一个 xidel 实例来解析该对象。特别是当你有一个非常大的 JSON 时,这非常慢。

高效file:write()方法:

xidel -s input.json -e '
  $json() ! file:write(
    .||".json",
    $json(.),
    {"method":"json"}
  )
'

一个 xidel 调用创建 'item{1,2,3}.json'。它们的内容是一个 compact/minified 对象,例如 {"a": 1} for 'item1.json'.

xidel -s input.json -e '
  for $x in $json() return
  file:write(
    concat($x,".json"),
    $json($x),
    {
      "method":"json",
      "indent":true()
    }
  )
'

一个 xidel 调用创建 'item{1,2,3}.json'。他们的内容是一个美化对象(因为{"indent":true()}),比如...

{
  "a": 1
}

...对于 'item1.json'。不同的查询(for 循环),相同的结果。

这种方法要快很多!