Home > Software engineering >  How to use(read) value from associative array during jq map?
How to use(read) value from associative array during jq map?

Time:04-26

I am reading aws ssm parameters via jq with json, and want to put them into a yaml file after some processing and alias mapping.

I have one associative array of mapping parameter name to some internal name (see process.sh)

My simplified example.json is

{
  "Parameters": [
    {
      "Name": "/dev/applications/web/some_great_key",
      "Value": "magicvaluenotrelevant"
    },
    {
      "Name": "/dev/applications/web/api_magic",
      "Value": "blabla"
    }
  ]
}

My bash script process.sh is

#!/usr/bin/env bash

declare -A ssmMap
ssmMap[/dev/applications/web/some_great_key]=theGreatKEYAlias
ssmMap[/dev/applications/web/api_magic]=apiKey

jq -r '
  .Parameters
  | map({
        Name: .Name,
        parameterValue: .Value
    })
  | map((${!ssmMap[.Name]}   ": \""   .parameterValue   "\""))
  | join("\n")
' < example.json;

I want/expected the output to be:

ssm_theGreatKEYAlias: "magicvaluenotrelevant"
ssm_apiKey: "singleblabla"

With the process.sh script that I provided I get error because cannot find a way to use the associative array sshMap inside jq map, to transform the parameter name from json into the mapped alias from sshMap.

Any idea how that can be achieved ?

If I change the line 13 of process.sh into

  | map((.Name   ": \""   .parameterValue   "\""))

it works fine but without mapping, uses original parameter name as comes from json file.

CodePudding user response:

You're trying to access a shell var from jq.

Fixed:

ssm_map='
   {
      "some_great_key": "theGreatKEYAlias",
      "api_magic":      "apiKey"
   }
'

jq -r --argjson ssm_map "$ssm_map" '
   .Parameters[] |
   "ssm_\( $ssm_map[ .Name ] ): \"\( .Value )\""
'

Demo on jqplay

You could convert the variable you describe into JSON with varying levels of difficulty (depending on what limitations, if any, you're willing to accept). But since you're building the variable from the output of yq, should could simply have it output JSON directly.

CodePudding user response:

Using mikefarah/yq or kislyuk/yq or itchyny/gojq is definitely the better approach if your actual task is to convert from YAML and to process as JSON.

However, to accomplish the task you have described in the original question, one could add the keys and values of the bash associative array using the --args option and access them within jq via the $ARGS.positional array (requires jq version 1.6), then restore the association by transposeing both halves of that array, and create an INDEX using the key from the first half, which can then be used with JOIN to create the desired text lines, which are output as raw text using the -r option.

jq -r '
  JOIN(
    $ARGS.positional | [.[:length/2], .[length/2:]] | transpose | INDEX(.[0]);
    .Parameters[];
    .Name;
    "ssm_\(.[1][1] // .[0].Name): \(.[0].Value)"
  )
' example.json --args "${!ssmMap[@]}" "${ssmMap[@]}"
ssm_theGreatKEYAlias: magicvaluenotrelevant
ssm_apiKey: blabla

The fallback // .[0].Name is unnecessary for the sample file, but was added to use the original key in case there's an input key not covered by the bash array.

  • Related