1

I actually have 2 arrays in bash that contains string values. Something like that :

Array1=(Kevin Paul)
Array2=(OK DANGER)

I would like to create a json with 2 attributes, something like that if possible

{
   "results":[
      {
         "nom":"Kevin",
         "status":"OK"
      },
      {
         "nom":"Paul",
         "status":"Danger"
      }
   ]
}

I read a lot speaking about JQ that i alreay use for my arrays, but no one speak about something like i want :(

One of my test ( that does not respond to what i would like ) :

declare -a test_array
declare -a test_array2
test_array=(apple orange lemon)
test_array2=(DANGER OK WARNING)
echo ${test_array[0]}

echo '['
printf '{"CVEC": "%s", "LVL" : "%s"},\n' "${test_array[@]}, ${test_array2[@]}" | sed '$s/,$//'
echo ']'

Display 

[
{"CVEC": "apple", "LVL" : "orange"},
{"CVEC": "lemon, DANGER", "LVL" : "OK"},
{"CVEC": "WARNING", "LVL" : ""}
]
9
  • The reason to use jq is that it ensures valid JSON no matter what values are stored in the arrays. A pure bash approach requires you to do all the examination of the values to ensure things that need to be escaped are handled properly. Commented Jun 23, 2020 at 12:31
  • Yes sure, but i don't have found anything for bash and build of json that respond to this :( Commented Jun 23, 2020 at 12:36
  • That's because bash doesn't have a built-in way to safely process produce JSON. Commented Jun 23, 2020 at 12:37
  • It seems you are looking for a zip function. eg. github.com/stedolan/jq/issues/609 Commented Jun 23, 2020 at 13:11
  • No sry, not at all what i need Commented Jun 23, 2020 at 13:11

3 Answers 3

1

Using a template engine: perl's Template::Toolkit command line tool: tpage:

Files

header:

{
   "results":[

footer:

   ]
}

file.tpl (template):

    {
        "nom": "[% x1 %]",
        "status": "[% x2 %]"
    }[% sep %]

Bash script

#!/bin/bash

arr1=( Kevin Paul  )
arr2=( OK danger )

{
    cat header
    for i in "${!arr1[@]}"; do
        ((i==${#arr1[@]}-1)) && sep='' || sep=','
        tpage --define x1="${arr1[i]}" \
              --define x2="${arr2[i]}" \
              --define sep=$sep file.tpl
    done
    cat footer
} | tee file.json

Validation

$ jq . file.json
{
  "results": [
    {
      "nom": "Kevin",
      "status": "OK"
    },
    {
      "nom": "Paul",
      "status": "danger"
    }
  ]
}

Package

For debian and debian like:

apt install libtemplate-perl

Via CPAN:

cpan -i Template::Toolkit

Check http://www.template-toolkit.org/docs/tools/tpage.html

Sign up to request clarification or add additional context in comments.

Comments

0

One way:

paste <(printf "%s\n" "${Array1[@]}") <(printf "%s\n" "${Array2[@]}") |
    jq -nRc '{ results: [inputs] | map(split("\t") | { nom: .[0], status: .[1] }) }'

produces

{"results":[{"nom":"Kevin","status":"OK"},{"nom":"Paul","status":"DANGER"}]}

This assumes that the elements of your arrays do not have tabs or newlines in them. It uses paste to generate pairs of corresponding array elements, separated by tabs, one pair per line, and then uses jq to create the JSON output from that.

Comments

0

If the objective is to stick with a non-jq solution - and chepner's comments about needing to validate the array entries is not an issue for this situation - one idea would be to loop through the array indices.

Test data:

$ declare -a test_array=(apple orange lemon)
$ typeset -p test_array
declare -a test_array=([0]="apple" [1]="orange" [2]="lemon")

$ declare -a test_array2=(DANGER OK WARNING)
$ typeset -p test_array2
declare -a test_array2=([0]="DANGER" [1]="OK" [2]="WARNING")

A simple loop through the indices (0,1,2):

sfx=','                                                   # default printf suffix is a comma

for (( i=0 ; i<${#test_array[@]} ; i++ ))
do
    (( ${i} == ( ${#test_array[@]} - 1 ) )) && sfx=''     # clear suffix for last pass through loop

    printf '{"CVEC": "%s", "LVL" : "%s"}%s\n' "${test_array[${i}]}" "${test_array2[${i}]}" "${sfx}"
done

Which generates the following:

{"CVEC": "apple", "LVL" : "DANGER"},
{"CVEC": "orange", "LVL" : "OK"},
{"CVEC": "lemon", "LVL" : "WARNING"}

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.