Building a json from jq

jqjsonlinuxshellshell-script

I want to generate a json file in jq like this below :

{
  "cpe": "dabb8fbd-d7be-4175-abb4-c628bb8cf1b5",
  "ps": [ "Obev" ],
  "ets": 5,
  "pMap": {
      "aik": ["1~4-b7-4c-bb-b~od1.y.1..aiq~s-an-6~-a-1", "1~4-b7-4c-bb-b~od1.y.1..aiq~s-an-6~-a-2", "1~4-b7-4c-bb-b~od1.y.1..aiq~s-an-6~-a-3", "1~4-b7-4c-bb-b~od1.y.1..aiq~s-an-6~-a-4", "1~4-b7-4c-bb-b~od1.y.1..aiq~s-an-6~-a-5"]
    }

Here is what I am trying in jq –

inner2=$(jq -n --arg aik "1~4-b7-4c-bb-b~od1.y.1..aiq~s-an-6~-a-1", "1~4-b7-4c-bb-b~od1.y.1..aiq~s-an-6~-a-2", "1~4-b7-4c-bb-b~od1.y.1..aiq~s-an-6~-a-3", "1~4-b7-4c-bb-b~od1.y.1..aiq~s-an-6~-a-4", "1~4-b7-4c-bb-b~od1.y.1..aiq~s-an-6~-a-5" \
              '$ARGS.named')

res=$(jq -n   --arg cpe "App" \
              --arg ps "["Obev"]" \
              --arg ets 5 \
              --argjson pMap "$inner2" \
              '$ARGS.named')

but it doesn't returns the JSON format as expected.
ets value if 5 which is int hence no quotes expected but it generates one
pMap value generates like this "aik": {"1~4-b7-4c-bb-b~od1.y.1..aiq~s-an-6~-a-1, 1~4-b7-4c-bb-b~od1.y.1..aiq~s-an-6~-a-2, 1~4-b7-4c-bb-b~od1.y.1..aiq~s-an-6~-a-3, 1~4-b7-4c-bb-b~od1.y.1..aiq~s-an-6~-a-4, 1~4-b7-4c-bb-b~od1.y.1..aiq~s-an-6~-a-5"}

here as per desired op the format is not getting generated

ps value is also not getting generated as per desired op

Any help would be great

Best Answer

Using jo (see here), which makes it easier to create JSON on the command line than what jq does. It allows for creating arrays with jo -a.

jo -p \
        cpe='dabb8fbd-d7be-4175-abb4-c628bb8cf1b5' \
        ps="$( jo -a Obev )" \
        ets=5 \
        pmap="$( jo aik="$( jo -a \
                "1~4-b7-4c-bb-b~od1.y.1..aiq~s-an-6~-a-1" \
                "1~4-b7-4c-bb-b~od1.y.1..aiq~s-an-6~-a-2" \
                "1~4-b7-4c-bb-b~od1.y.1..aiq~s-an-6~-a-3" \
                "1~4-b7-4c-bb-b~od1.y.1..aiq~s-an-6~-a-4" \
                "1~4-b7-4c-bb-b~od1.y.1..aiq~s-an-6~-a-5" )" )"

Assuming that you are using a shell that has arrays, and that ets is the length of the aik array:

data=(
        "1~4-b7-4c-bb-b~od1.y.1..aiq~s-an-6~-a-1"
        "1~4-b7-4c-bb-b~od1.y.1..aiq~s-an-6~-a-2"
        "1~4-b7-4c-bb-b~od1.y.1..aiq~s-an-6~-a-3"
        "1~4-b7-4c-bb-b~od1.y.1..aiq~s-an-6~-a-4"
        "1~4-b7-4c-bb-b~od1.y.1..aiq~s-an-6~-a-5"
)

jo -p \
        cpe='dabb8fbd-d7be-4175-abb4-c628bb8cf1b5' \
        ps="$( jo -a Obev )" \
        ets="${#data[@]}" \
        pmap="$( jo aik="$( jo -a "${data[@]}" )" )"

The -p option for jo make sit pretty-print the output, so remove that when you are happy with that the document's structure is correct.


The corresponding jq command, assuming the array data exists, is

jq -n \
        --arg cpe 'dabb8fbd-d7be-4175-abb4-c628bb8cf1b5' \
        --argjson ps "$( jq -n '$ARGS.positional' --args Obev )" \
        --arg ets "${#data[@]}" \
        --argjson pmap "$(
                jq -n --argjson aik "$( jq -n '$ARGS.positional' --args "${data[@]}" )" \
                        '$ARGS.named'
        )" \
        '$ARGS.named'

That is, use

jq -n '$ARGS.positional' --args some arguments here

to create an anonymous array.