skip to Main Content

I’m simply trying to replace an objects value in a json file with an array, using jq in a bash script.
The json file (truncated) looks like this:

{
  "objects": {
    "type": "foo",
    "host": "1.1.1.1",
    "port": "1234"
  }
}

I want to replace the host objects value with an array of different values, so it looks like this:

{
  "objects": {
    "type": "foo",
    "host": ["1.1.1.1","2.2.2.2"],
    "port": "1234"
  }
}

I tested around with this script. The Input comes from a simple, comma separated string which I convert into a proper json array (which seems to work).
But I’m not able replace the value with the array.

#!/bin/bash
objectshost="1.1.1.1,2.2.2.2"
objectshost_array=$(jq -c -n --arg arg $objectshost '$arg|split(",")')

jq --arg value "$objectshost_array" '.objects.host = $value' ./test.json > ./test.json.tmp

The best I ended up with, is this:

{
  "objects": {
    "type": "foo",
    "host": "["1.1.1.1","2.2.2.2"]",
    "port": "1234"
  }
}

The result seems to be some logical result, as the script simply replaces the value with the arrays string. But it’s not what I expected to get. đŸ˜‰

I found some similar questions, but all of them were dealing with replacing values in existing arrays or key/value pairs, but my problem seems to be the conversion from a single value to an array.

Can somebody please push me into the right direction? Or should I forget about jq and threat the json file as a simple text file?

Thanks in advance,
André

2

Answers


  1. You can do it with a single jq command:

    #!/bin/sh
    objectshost="1.1.1.1,2.2.2.2"
    
    jq --arg value "$objectshost" '.objects.host = ($value / ",")' ./test.json > ./test.json.tmp
    

    This has the added benefit of not requiring Bash arrays, but can be used with any shell.


    If you already have a JSON array, you must use --argjson and not --arg. --arg always creates a variable of type string, --argjson however parses the value as JSON entity.

    #!/bin/bash
    objectshost="1.1.1.1,2.2.2.2"
    objectshost_array=$(printf '%sn' "$objectshost" | jq -c 'split(",")')
    
    jq --argjson value "$objectshost_array" '.objects.host = $value' ./test.json > ./test.json.tmp
    
    Login or Signup to reply.
  2. It would work with a conditional assignment from arguments:

    jq '
    .objects.host = (
      .objects.host |
      if type == "array"
      then .
      else [ . ]
      end + $ARGS.positional
    )
    ' input.json --args 1.2.3.4 2.2.2.2 4.4.4.4
    

    Or the same as a stand-alone jq script; which is more readable and maintainable:

    myJQScript:

    #!/usr/bin/env -S jq --from-file --args
    
    .objects.host = (
      .objects.host |
      if type == "array"
      then .
      else [ . ]
      end + $ARGS.positional
    )
    

    Make it executable:

    chmod +x myJQScript
    

    Run it with arguments to add array entries to host

    $ ./myJQScript 1.2.3.4 2.2.2.2 4.4.4.4 < input.json
    {
      "objects": {
        "type": "foo",
        "host": [
          "1.1.1.1",
          "1.2.3.4",
          "2.2.2.2",
          "4.4.4.4"
        ],
        "port": "1234"
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search