Home > Blockchain >  How to perform a check on multiple sub-trees
How to perform a check on multiple sub-trees

Time:05-18

What I'm trying to do currently, is, between both environments, 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.

CodePudding user response:

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

CodePudding user response:

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
  • Related