简体   繁体   中英

Pass nested json key to jq from bash variable

I'm trying to parse some json with jq that looks like this:

{
    "currentServerId": 1,
    "isCurrentServerAvailable": true,
    "isClusterOwner": false,
    "clusterOwnerServerId": "2",
    "numInvalidEventMessages": "0",
    "numInvalidoperationalStateMessages": "0",
    "servers": {
        "1": {
            "isAvailableViaServerObjective": true,
            "eventMessagesPendingInDb": "0",
            "neo4jClusterRole": "slave",
            "monitoredServerHealth": null
        },
        "2": {
            "isAvailableViaServerObjective": true,
            "eventMessagesPendingInDb": "0",
            "neo4jClusterRole": "master",
            "monitoredServerHealth": {
                "serverId": 2,
                "healthState": "ALIVE",
                "healthCount": 1,
                "serverIdAsString": "2",
                "serverUid": "*"
            }
        },
        "3": {
            "isAvailableViaServerObjective": true,
            "eventMessagesPendingInDb": "0",
            "neo4jClusterRole": "slave",
            "monitoredServerHealth": null
        }
    }
}

I can obtain the value I need with a filter like this:

 # cat test.json | jq .'servers."2".monitoredServerHealth.healthState'
"ALIVE"

If I pass in a single variable as a key it works:

# echo $var 
servers

# cat json.tst | jq --arg keyvar "$var" '.[$keyvar]'
{
  "1": {
    "isAvailableViaServerObjective": true,
    "eventMessagesPendingInDb": "0",
    "neo4jClusterRole": "slave",
    "monitoredServerHealth": null
  },
<omitted the rest for brevity>

When I try to do the same for a nested block (where one level of the key is from a variable), it fails. I've tried a number of variations but they all fail.

What is the correct syntax?

# echo $var
"2"

# cat test.json | jq --arg keyvar "$var" '.servers.$[keyvar].monitoredServerHealth.healthState'
jq: error: syntax error, unexpected '$', expecting FORMAT or QQSTRING_START (Unix shell quoting issues?) at <top-level>, line 1:
.servers.$[keyvar].monitoredServerHealth.healthState         
jq: 1 compile error

Split up the path into two parts:

$ jq --arg keyvar "$var" '.servers | .[$keyvar].monitoredServerHealth.healthState' input.json
"ALIVE"

From the documentation:

A filter of the form .foo.bar is equivalent to .foo|.bar.

I don't know why it doesn't work combined as .servers.[$keyvar] ; might be a parser bug or something. At least the workaround is trivial.


Another way uses string interpolation:

jq --arg keyvar "$var" '.servers."\($keyvar)".monitoredServerHealth.healthState' input.json

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM