Search code examples
yamlyq

How to modify YAML object with given key in object array?


I have the following file contents:

animals:
  - rabbit:
      type: R
  - dog:
      type: D
  - cat:
      type: C

What I would want to do with yq is to find all keys that have an "a" in them ("cat" and "rabbit") and modify the file in place to add a "has_a: true" property, so end up with:

animals:
  - rabbit:
      has_a: true
      type: R
  - dog:
      type: D
  - cat:
      has_a: true
      type: C

Ideally, I'd add the property at the first position, but don't modify any existing keys.

Could someone please give me a pointer how to do this with yq? I tried a whole bunch of things, but can't figure it out.


Solution

  • This works with both implementations of yq:

    .animals[] |= with_entries(select(.key | contains("a")).value.has_a = true)
    
    animals:
      - rabbit:
          type: R
          has_a: true
      - dog:
          type: D
      - cat:
          type: C
          has_a: true
    

    Use the -i option to modify the file in-place. For kislyuk/yq, also add the -y option to produce YAML.


    Ideally, I'd add the property at the first position

    Properties only have an order in their representation. Logically, they are identical to any other order, and other tools along your processing chain could just revert any effort of ordering them. That said, you could make yq (both implementations in their currrent versions - this might change in the future) to output the new key first by adding the old value to it (in this order):

    .animals[] |= with_entries(select(.key | contains("a")).value |= {"has_a": true} + .)
    
    animals:
      - rabbit:
          has_a: true
          type: R
      - dog:
          type: D
      - cat:
          has_a: true
          type: C
    

    Tested with kislyuk/yq 3.2.3, and mikefarah/yq 4.34.2