David Gard
David Gard

Reputation: 12047

Use jq to replace many values with variable values

Using jq, is it possible to replace the value of each parameter in the sample JSON with the value of the variable that is the initial value?

In my scenario, Azure DevOps does not carryout any kind of variable substitution on the JSON file, so I need to do it manually. So for example, say $SUBSCRIPTION_ID is set to abc-123, I'd like to use jq to update the JSON file.

I can pull out the values using .parameters[].value, but I can't seem to find a way of setting each individual value.

The main challenge here is that the solution should be reusable, and different JSON files will have different parameters, so I don't think I can use --argjson.

Example

Original JSON

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/parametersTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "subscriptionId": {
            "value": "$SUBSCRIPTION_ID"
        },
        "topicName": {
            "value": "$TOPIC_NAME"
        }
    }
}

Variables

SUBSCRIPTION_ID="abc-123"
TOPIC_NAME="SomeTopic"

Desired JSON

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/parametersTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "subscriptionId": {
            "value": "abc-123"
        },
        "topicName": {
            "value": "SomeTopic"
        }
    }
}

Upvotes: 5

Views: 1754

Answers (3)

oguz ismail
oguz ismail

Reputation: 50750

Export those variables so that you can access them from within jq.

export SUBSCRIPTION_ID TOPIC_NAME
jq '.parameters[].value |= (env[.[1:]] // .)' file

//. part is for leaving variables absent in the environment as is, you can drop it if not necessary

Upvotes: 3

peak
peak

Reputation: 116690

Here is a "data-driven" approach based on the contents of the schema and the available environment variables:

export SUBSCRIPTION_ID="abc-123"
export TOPIC_NAME="SomeTopic"

< schema.json jq '.parameters 
    |= map_values(if .value | (startswith("$") and env[.[1:]]) 
                  then .value |= env[.[1:]] else . end)'

Notice that none of the template names appear in the jq program.

If your shell supports it, you could avoid the "export" commands by prefacing the jq command with the variable assignments along the lines of:

SUBSCRIPTION_ID="abc-123" TOPIC_NAME="SomeTopic" jq -f program.jq schema.json

Caveat

Using environment variables to pass in the parameter values may not be such a great idea. Two alternatives would be to provide the name-value pairs in a text file or as a JSON object. See also Using jq as a template engine

Upvotes: 1

chepner
chepner

Reputation: 530960

Use --argjson; essentially, you are just going to ignore the attempt at parameterizing the JSON and simply replace the values unconditionally.

jq --argjson x "$SUBSCRIPTION_ID" \
   --argjson y "$TOPIC_NAME" \
   '.parameters.subscriptionId.value = $x; .parameters.topicName.value = $y' \
   config.json

Upvotes: 4

Related Questions