2

I'm passing a JSON object to jq and want to add extra objects to an inner array ('accessories') if its parent array ('platforms') matches a certain name.

Here's my source JSON:

    {
        "bridge": {
            "name": "Homebridge",
            "port": 51395
        },
        "accessories": [],
        
        "platforms": [
            {
                "name": "Config",
                "port": 8581,
                "platform": "config"
            },
            {
                "platform": "homebridge-cbus.CBus",
                "name": "CBus",
                "client_ip_address": "127.0.0.1",
                "accessories": [
                    {
                      "values": "existing"
                    }
                ]
            }
        ]
    } 

This works beautifully:

    jq '.platforms[1].accessories +=  [{ "values" : "NEW" }]'

... but of course it's poor form to expect platforms[1] to always the be array I want to append to, so I set about trying to form the right syntax for a search or if/then/else to only act on the .name of the appropriate one.

I thought this was my solution:

    jq '.platforms[] | if ( .name=="CBus" ) then .accessories += [{ "values" : "NEW" }] else . end'

... until I realised it was only passing the 'platforms' through and eating the 'bridge' object and empty outer 'accessories' array, which I need to retain.

My issue looks to be similar to JQ | Updating array element selected by `select`, but I've tried LOTS of combinations but just can't break through.

Edit: Here's the correct JQPlay I've been working with:

https://jqplay.org/s/dGDswqAEte

Thanks for any help.

2
  • Your jqplay snippet and the one in the question look to be different problems Commented Jul 13, 2020 at 12:28
  • Sorry, you are totally correct. I had not correctly shared my JQPlay. Corrected now. Commented Jul 13, 2020 at 20:33

1 Answer 1

2

That's a good attempt. The key here is to use the select() function to identify the object you are going to update and overwrite the overall array using |= operator, i.e.

.platforms |= ( map(select(.name == "CBus").accessories += [{ "values" : "NEW" }]  ) )

For the snippet in your jq-play link (now removed), you need to do

.gcp_price_list."CP-COMPUTEENGINE-OS" 
    |= with_entries(select(.value.cores == "shared").value.cores = "0.5")

Or if you want to be even more specific, and keep the entry in gcp_price_list configurable, do

.gcp_price_list |= 
with_entries ( 
  select(.key == "CP-COMPUTEENGINE-OS").value  |=  
with_entries(
  select(.value.cores == "shared").value.cores = "0.5") )
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.