Search code examples
yq

Aggregating yq maps after selection


Using https://github.com/mikefarah/yq, I am trying to create a simple new map from nested keys and values but can't find how to merge everything properly after filtering

paths:
  /openapi.yaml:
    get:
      operationId: AdminPing
      x-required-scopes:
        - test-scope
  /user/{id}:
    delete:
      operationId: DeleteUser
      x-required-scopes:
        - test-scope
        - users:write
    put:
      operationId: UpdateUser

should output the following:

{
  "AdminPing": [
    "test-scope"
  ],
  "DeleteUser": [
    "test-scope",
    "users:write"
  ]
}

but the closest I've come is multiple objects:

yq -o=json e '.paths[][] | {.operationId: .x-required-scopes} | del(.[] | select(tag == "!!null"))' test-spec.yaml 
{
  "AdminPing": [
    "test-scope"
  ]
}
{
  "DeleteUser": [
    "test-scope",
    "users:write"
  ]
}
{}

and separated items

yq -o=json e '[.paths[][] | {.operationId: .x-required-scopes} | del(.[] | select(tag == "!!null"))]' test-spec.yaml
[
  {
    "AdminPing": [
      "test-scope"
    ]
  },
  {
    "DeleteUser": [
      "test-scope",
      "users:write"
    ]
  }
]

Solution

  • You could use ireduce to iteratively build up the object:

    yq -o=json e '
      .paths[][] | {.operationId: .x-required-scopes}
      | select(.[]) as $i ireduce ({}; . + $i)
    ' test-spec.yaml
    
    {
      "AdminPing": [
        "test-scope"
      ],
      "DeleteUser": [
        "test-scope",
        "users:write"
      ]
    }