Nicholas Rinaldi
Nicholas Rinaldi

Reputation: 145

How to perform a check on multiple sub-trees

What I'm trying to do currently, is, within each environment, compare mainAccount and secondAccount values.

If they do match, then I will trigger some downstream code to check the file version. If they do not, then I will pass. That is not really relevant, however I am struggling to compare the values across each environment. Since each .json file will have different amounts of environments.

Meaning, in testing environment, I want to check if mainAccount = secondAccount, and same in production environment.

I'm running into issues parsing this JSON with jq:

json1

{
    "file_version": 1.0,
    "config": [
        {
            "environment": "testing",
            "main": [
                {
                    "mainAccount": "123"
                }
            ],
            "second": [
                {
                    "secondAccount": "456"
                }
            ]
        },
        {
            "environment": "production",
            "main": [
                {
                    "mainAccount": "789"
                }
            ],
            "second": [
                {
                    "secondAccount": "789"
                }
            ]
        }
    ]
}

Here's another sample .json file for comparsion:

json2

    {
    "file_version": 1.3,
    "config": [
        {
            "environment": "testing",
            "main": [
                {
                    "mainAccount": "123"
                }
            ],
            "second": [
                {
                    "secondAccount": "456"
                }
            ]
        },
        {
            "environment": "production",
            "main": [
                {
                    "mainAccount": "789"
                }
            ],
            "second": [
                {
                    "secondAccount": "789"
                }
            ]
        },
        {
            "environment": "pre-production",
            "main": [
                {
                    "mainAccount": "456"
                }
            ],
            "second": [
                {
                    "secondAccount": "789"
                }
            ]
        },
        {
            "environment": "staging",
            "main": [
                {
                    "mainAccount": "234"
                }
            ],
            "second": [
                {
                    "secondAccount": "456"
                }
            ]
        }
    ]
}

If I run this command:

jq -r '.config[] | select(.main != null) | .main[].mainAccount

My output is:

123
789

If i store this output in a variable, it'll be 123 789 so comparing this to the "secondAccount" value is troublesome.

I think what I'm looking for is iteration here, however, I'm not sure how to implement this. I wanted to take a pythonic approach to check the length of the config array, create a for loop in that length range, then collect the value based on an index like

.config[0] | select(.main != null) | .main[].mainAccount
.config[1] | select(.main != null) | .main[].mainAccount

etc. The issue however, is that when I read in the .config[] value as a variable, bash doesn't interpret it like that. The length will be the length of characters, not, the amount of objects in the array.

EXPECTED OUTPUT Nothing. I simply want to, for each .json file above, compare the mainAccount and secondAccount values with eachother, within each environment.

In json1, I want to compare mainAccount == secondAccount in environment: testing. Then mainAccount == secondAccount in environment: production.

Then move onto json 2 and compare mainAccount == secondAccount in environment: testing. Then environment production, pre-production, staging, so on and so forth.

Upvotes: 0

Views: 118

Answers (2)

A.H.
A.H.

Reputation: 66263

Since all information is within this one JSON file it is better to do the processing in jq as much as possible and to keep the shell out.

Given your input you can try this jq:

jq '
    .config[]
    | {
        environment,
        condition: (.main[0].mainAccount == .second[0].secondAccount)
    }' input.json

The result is:

{
  "environment": "testing",
  "condition": false
}
{
  "environment": "production",
  "condition": true
}

Some questions though:

  • Why are the values of first and second arrays objects and not object?
  • Is it really intended to match the first one of both?
  • Can there be more items in the arrays?

Also: If you want to process the results in a shell, I propose this expression because the output can be used (source or eval) in a shell:

jq -r '
    .config[]
    | "\(.environment)=\(.main[0].mainAccount == .second[0].secondAccount)"' input.json

The output is:

testing=false
production=true

Upvotes: 1

pmf
pmf

Reputation: 36151

You can do the comparison within jq, return the boolean result as its exit status using the -e option, and react upon that in bash, e.g. using an if statement.

if jq -e '
  .config | map(select(.main != null) | .main[].mainAccount) | .[0] == .[1]
' file.json >/dev/null
then echo "equal"
else echo "not equal"
fi
not equal

Upvotes: 0

Related Questions