Alex Harvey
Alex Harvey

Reputation: 15502

Editing value in nested array using variables

I have the following JQ problem that I can't solve. Given JSON:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::111122223333:root"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

I need to take the value .Principal.AWS and save that in a variable $orig or something, and then readd that variable as an element in an array that will become the new document.

This almost works:

'.Statement[0]
    | .Principal.AWS as $orig
    | .Principal.AWS = [$orig] + ["foo", "bar"]'

Doing that, however, I lose the Version and Statement level. Meanwhile, doing this nearly does what I want:

'(.Statement[] | .Principal.AWS) = ["foo", "bar"]'

So I expected this to also work but it doesn't:

'(.Statement[] | .Principal.AWS as $orig | .Principal.AWS) = [$orig, "foo", "bar"]'

Then I get an invalid path expression error.

How can I correct this syntax? The expected result is:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": ["arn:aws:iam::111122223333:root", "foo", "bar"]
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

Upvotes: 2

Views: 58

Answers (2)

Jeff Mercado
Jeff Mercado

Reputation: 134611

You just need to ensure that you don't change the input context using pipes at the top level. Assignments preserve the input so try to write your filter as an assignment.

The intermediate variable is unnecessary, you could do without it. I'd write it like this:

.Statement[].Principal.AWS |= [(arrays // [.])[], "foo", "bar"]

If Principal.AWS was already an array, it'll just append your new values to that array, otherwise assumes the current value is the first item of the new array.

Upvotes: 1

Inian
Inian

Reputation: 85895

A simple addition to your already well made attempt is all you need. Replace the | with the update assignment and optionally group into parenthesis (..). The part after |= recreates the object from . and assigns to the path on the LHS

.Statement[0] |= ( .Principal.AWS as $orig | .Principal.AWS = [$orig] + ["foo", "bar"] )
#            ^^^

Upvotes: 1

Related Questions