简体   繁体   中英

Selecting from complex nested JSON data in JQ

I have JSON data like this:

{
  "profiles": {
    "auto_scaler": [
      {
        "auto_scaler_group_name": "myasg0",
        "auto_scaler_group_options": {
          ":availability_zones": ["1a", "1b", "1c"],
          ":max_size": 1,
          ":min_size": 1,
          ":subnets": ["a", "b", "c"],
          ":tags": [
            {":key": "Name", ":value": "app0" },
            {":key": "env", ":value": "dev" },
            {":key": "role", ":value": "app" },
            {":key": "domain", ":value": "example.com" },
            {":key": "fonzi_app", ":value": "true"},
            {":key": "vpc", ":value": "nonprod"}
          ]
        },
        "dns_name": "fonz1"
      },
      {
        "auto_scaler_group_name": "myasg1",
        "auto_scaler_group_options": {
          ":availability_zones": ["1a", "1b", "1c"],
          ":max_size": 1,
          ":min_size": 1,
          ":subnets": ["a", "b", "c"],
          ":tags": [
            {":key": "Name", ":value": "app1" },
            {":key": "env", ":value": "dev" },
            {":key": "role", ":value": "app" },
            {":key": "domain", ":value": "example.com" },
            {":key": "bozo_app", ":value": "true"},
            {":key": "vpc", ":value": "nonprod"}
          ]
        },
        "dns_name": "bozo1"
      }
    ]
  }
}

I want to write a jq query to firstly select the Hash element in the Array at .profiles.auto_scaler whose Array of Hashes at .auto_scaler_group_options.tags contains Hashes containing a " :key " key whose value contains " fonzi " and a " :value " key whose value is exactly true and then return the value of the key dns_name .

In the example, the query would simply return "fonz1" .

Does anyone know how to do this, if it is possible, using jq?

In brief, yes.

In long:

.profiles.auto_scaler[]
| .dns_name as $name
| .auto_scaler_group_options
| select( any(.[":tags"][];
             (.[":key"] | index("fonzi")) and (.[":value"] == "true")) )
| $name

The output of the above is:

"fonz1"

The trick here is to extract the candidate .dns_name before diving more deeply into your "complex nested JSON".

An alternative

If your jq does not have any , you could (in this particular case) get away without it by replacing the select expression above with:

 select( .[":tags"][]
         | (.[":key"] | index("fonzi")) and (.[":value"] == "true") )

Be warned, though, that the semantics of the two expressions are slightly different. (Homework exercise: what is the difference?)

If your jq doesn't have any and if you want the semantics of any , then you could easily roll your own, or simply upgrade :-)

You can lookup JSON in number or ways ,

  1. by checking property exists or not
  2. by using [property] syntax,
  3. 'property' in object syntax

for your case , here's a small sample , further you can lookup on array and see

containing a "key" key whose value contains EEE and a "value" key whose value is exactly FFF

for(var k=0; k < p['AAA']['BBB'].length;k++){  
   console.log(p['AAA']['BBB'][k]) 
}

where p is JSON object.

Hope that helps

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