jq icon indicating copy to clipboard operation
jq copied to clipboard

Сreating multilevel json with the jq utility in a bash script

Open AndryAsh opened this issue 1 year ago • 2 comments

I get the contents of a text file into an array and then sequentially get the elements of the array and try to add the elements to the json:

#!/bin/bash

JSON=$(jq -n '')
readarray -t array < ./station.sample
count=0

for e in "${array[@]}"
do
    if echo "$e" | grep -Eq '^[0-9]{10}' >/dev/null
      then
        timestamp=$e
        datetime=`date +'%Y-%m-%d %H:%M:%S' -d "@$e"`
        JSON=$(echo $JSON | jq --arg timestamp "${timestamp}" '. += $ARGS.named')
        JSON=$(echo $JSON | jq --arg datetime "${datetime}" '. += $ARGS.named')
    fi

    if echo "$e" | grep '^Station ' >/dev/null
      then
        NODE=$(jq -n '')
        mac=`echo "$e" | awk '{ print $2 }'`
        interface=`echo "$e" | awk '{ print $4 }' | rev | cut -c2- | rev`

        JSON=$(echo $JSON | jq --argjson nodes "[]" '. += $ARGS.named')
        JSON=$(echo $JSON | jq --arg mac "${mac}" --arg count "${count}" '.nodes[0] += {"mac": $mac}')
    JSON=$(echo $JSON | jq --arg interface "${interface}" '.nodes[0] += {"interface": $interface}')

        count=$((count+1))
    fi
done

As a result, I get a json like this:

{
  "timestamp": "1721396365",
  "datetime": "2024-07-19 16:39:25",
  "nodes": [
    {
      "mac": "14:88:00:00:00:06"
    }
  ]
}

But I need to add multiple objects to the list, so I set a count variable and want to use it to specify the index of the list:

JSON=$(echo $JSON | jq --arg mac "${mac}" --arg count "${count}" '.nodes[$count] += {"mac": $mac}')

But in this variant adding list items doesn't work.

How can I dynamically specify the index of the list?

I've tried all the options that came to mind, but I haven't found a solution yet:

 NODE=$(echo $NODE | jq --arg mac "$mac" '. += $ARGS.named')
 NODE=$(echo $NODE | jq --arg interface "${interface}" '. += $ARGS.named')
 JSON=$(echo $JSON | jq --argjson node "${NODE}" '.nodes[.nodes | length] = $ARGS.named')

It is necessary to use a variable to specify the index of the list.

AndryAsh avatar Jul 26 '24 09:07 AndryAsh

Could you share a sample input file with at least five lines and its expected JSON result? Your use case looks achievable with one jq command but the expectated result is ambiguous.

itchyny avatar Jul 26 '24 10:07 itchyny

Something like .nodes += [{$mac}] should work.

itchyny avatar Jul 26 '24 11:07 itchyny