将多个对象合并到一个对象下,并在一个命令中添加兄弟对象

Merge multiple objects under a single object and add sibling object in one command

所以我有三个文件:

cats.json

{
  "cats": [
    {
      "name": "fluffles",
      "age": 10,
      "color": "white"
    }
  ]
}

dogs.json

{
  "dogs": [
    {
      "name": "sam",
      "age": 5,
      "color": "black and white"
    },
    {
      "name": "rover",
      "age": 2,
      "color": "brown and white"
    }
  ]
}

snakes.json

{
  "snakes": [
    {
      "name": "noodles",
      "age": 10,
      "color": "green"
    }
  ]
}

我想将它们合并到一个“动物”对象下。我发现这会合并文件:

jq -s '{"animals": .} ' cats.json dogs.json snakes.json > animals.json
{
  "animals": [
    {
      "cats": [
        {
          "name": "fluffles",
          "age": 10,
          "color": "white"
        }
      ]
    },
    {
      "dogs": [
        {
          "name": "sam",
          "age": 5,
          "color": "black and white"
        },
        {
          "name": "rover",
          "age": 2,
          "color": "brown and white"
        }
      ]
    },
    {
      "snakes": [
        {
          "name": "noodles",
          "age": 10,
          "color": "green"
        }
      ]
    }
  ]
}

现在我多了一个对象:

owners.json

{
  "owners": [
    "peter",
    "william",
    "sally"
  ]
}

我想使用

合并到同一个文件中
jq -s '.[0] + .[1]' animals.json owners.json

我可以只用一个 jq 命令来完成这两项操作吗?

jq -s '{"animals": .} ' cats.json dogs.json snakes.json > animals.json
jq -s '.[0] + .[1]' animals.json owners.json

结果如下所示:

{
  "animals": [
    {
      "cats": [
        {
          "name": "fluffles",
          "age": 10,
          "color": "white"
        }
      ]
    },
    {
      "dogs": [
        {
          "name": "sam",
          "age": 5,
          "color": "black and white"
        },
        {
          "name": "rover",
          "age": 2,
          "color": "brown and white"
        }
      ]
    },
    {
      "snakes": [
        {
          "name": "noodles",
          "age": 10,
          "color": "green"
        }
      ]
    }
  ],
  "owners": [
    "peter",
    "william",
    "sally"
  ]
}

不确定这是否是要走的路,但它通过以下方式获得所需的输出:

  • 使用--slurp:
  • 将前 3 个文件捕获为单个数组变量
    [ .[0] * .[1] * .[2] ] as $all
  • owners 对象作为单个变量捕获
    .[3].owners as $owners
  • 根据需要创建对象
    { "animals": $all, "owners": $owners }
jq \
    --slurp \
    '[ .[0] * .[1] * .[2] ] as $all | .[3].owners as $owners | { "animals": $all, "owners": $owners }' cats.json dogs.json snakes.json owners.json

将产生:

{
  "animals": [
    {
      "cats": [
        {
          "name": "fluffles",
          "age": 10,
          "color": "white"
        }
      ],
      "dogs": [
        {
          "name": "sam",
          "age": 5,
          "color": "black and white"
        },
        {
          "name": "rover",
          "age": 2,
          "color": "brown and white"
        }
      ],
      "snakes": [
        {
          "name": "noodles",
          "age": 10,
          "color": "green"
        }
      ]
    }
  ],
  "owners": [
    "peter",
    "william",
    "sally"
  ]
}

假设您有一个(先验的)不确定的或大量的动物类型,并且只有一个 owners 文件。在这种情况下,最好不要使用 -s 选项(以节省内存),并且使用所有者文件作为第一个数据文件调用 jq 会更容易,例如沿着:

jq -n -f program.jq owners.json $(ls *.json | grep -v owners.json)

其中 program.jq 包含如下程序:

input as $owners | {$owners, animals: [inputs]}

(注意 {"owners": $owners} 是如何缩写的。)