skip to Main Content

I would like to add a number of key:value pairs to an existing JSON string. The values are passed as command line arguments to my script.

So far I’ve got this

data='{"update": { "labels": [] } }'

for label in "${@}";do
   objJSON=$(printf '%sn' "{ "add": ${label} }" | jq -R . | jq -s .)
   data=$(echo ${data} | jq  --argjson jsonString "$objJSON" '.update.labels += $jsonString')
done
echo ${data} >output.txt

jq --color-output . output.txt

My output is this:

{
  "update": {
    "labels": [
      "{ add: value1 }",
      "{ add: value2 }"
    ]
  }
}

but I’m trying to get this (note the quotes surrounding add and each value):

{
  "update": {
    "labels": [
      { "add": "value1" },
      { "add": "value2" }
    ]
  }
}

I can’t see where I’m going wrong – can anyone help please?

3

Answers


  1. Since your add key is static, I’d only pass the value of the item you want to add using the correct key as varibale.

    Then you can add it by doing .. |= { $add }
    :

    jq --arg add "labelValue" '.update.labels |= { $add }' <<< "$data"
    
    Login or Signup to reply.
  2. Why not do everything in a single call to jq, using --args "$@" to transfer all arguments to jq, and therein the $ARGS.positional array to reference them:

    #!/bin/bash
    
    data='{"update": { "labels": [] } }'
    
    jq '.update.labels += [{add: $ARGS.positional[]}]' --args "$@" <<< "$data" > output.json
    

    Or, if you let jq also generate the initial document, it’s really just that one call:

    #!/bin/sh
    
    jq -n '.update.labels = [{add: $ARGS.positional[]}]' --args "$@" > output.json
    
    Login or Signup to reply.
  3. Make sure to escape your key/value quotes:

    for label in "$@"; do
        objJSON=$(echo "{ "add": "$label" }" | jq -c .)
    ###       escape here-^----^---^-------^   compact-^
        data=$(echo "$data" | jq --argjson jsonString "$objJSON" '.update.labels += [$jsonString]')
    done
    

    Here is a Bash script that handles adding new objects to the update labels array.

    #!/usr/bin/env bash
    
    DEFAULT_OUTPUT_FILENAME=output.txt
    
    # Function to display help
    show_help() {
        echo "Usage: $(basename "$0") [options] [label1] [label2] ... [labelN]"
        echo
        echo "This script takes key-value pair arguments and adds them to a JSON document."
        echo
        echo "Options:"
        echo "  -i, --input FILE   Input JSON file to append labels to (default: ${DEFAULT_OUTPUT_FILENAME})."
        echo "  -o, --output FILE  Output to FILE instead of ${DEFAULT_OUTPUT_FILENAME}."
        echo "  -h, --help         Display this help message."
        echo
        echo "Arguments:"
        echo "  labelN        The key-value pair to add to the JSON document."
        echo
        echo "Example:"
        echo "  $(basename "$0") "label1" "label2" "label3""
        echo "  $(basename "$0") -i existing.json -o updated.json "label1" "label2""
    }
    
    # Initialize variables
    input_file=${DEFAULT_OUTPUT_FILENAME}
    output_file=${DEFAULT_OUTPUT_FILENAME}
    
    # Parse options
    while [[ "$1" == -* ]]; do
        case "$1" in
            -i|--input)
                input_file="$2"
                shift 2
                ;;
            -o|--output)
                output_file="$2"
                shift 2
                ;;
            -h|--help)
                show_help
                exit 0
                ;;
            *)
                echo "Unknown option: $1"
                show_help
                exit 1
                ;;
        esac
    done
    
    # Ensure at least one label is provided
    if [[ $# -eq 0 ]]; then
        echo "No labels provided. Use -h or --help for usage information."
        exit 1
    fi
    
    # Initialize JSON data
    if [[ -f "$input_file" ]]; then
        data=$(cat "$input_file")
    else
        data='{"update": { "labels": [] } }'
    fi
    
    # Iterate over the labels
    for label in "$@"; do
        # Create JSON object from the label
        objJSON=$(echo "{ "add": "$label" }" | jq -c .)
        # Append the JSON object to the labels array
        data=$(echo "$data" | jq --argjson jsonString "$objJSON" '.update.labels += [$jsonString]')
    done
    
    # Output the final JSON to a file
    echo "$data" > "$output_file"
    
    # Pretty print the JSON
    jq --color-output . "$output_file"
    

    Here is the usage:

    [user@host ~]$ ./json_add.sh --help
    Usage: json_add.sh [options] [label1] [label2] ... [labelN]
    
    This script takes key-value pair arguments and adds them to a JSON document.
    
    Options:
      -i, --input FILE   Input JSON file to append labels to (default: output.txt).
      -o, --output FILE  Output to FILE instead of output.txt.
      -h, --help         Display this help message.
    
    Arguments:
      labelN        The key-value pair to add to the JSON document.
    
    Example:
      json_add.sh "label1" "label2" "label3"
      json_add.sh -i existing.json -o updated.json "label1" "label2"
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search