Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

JQ does not contain for "key": "value" JSON structure

The question is similar to THIS, but the JSON structure is different.

In my usecase JSON has an arrays with key:value data:

{
   "data":[
      {
         "name":"banana",
         "tags":[
            {
               "id":"yellow"
            },
            {
               "id":"long"
            }
         ]
      },
      {
         "name":"apple",
         "tags":[
            {
               "id":"red"
            },
            {
               "id":"round"
            }
         ]
      },
      {
         "name":"orange",
         "tags":[
            {
               "id":"orange"
            },
            {
               "id":"round"
            },
            {
               "id":"colored"
            }
         ]
      }
   ]
}

What required is to filter the only elements that do not have certain keyword – "red" for instance.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

When i use jq '.data[] | select(.tags[].id | index( "red" ))' it brings me the correct resut of ‘apple’ (as it has "id": "red") and ‘orange’ (as it has "id": "colored").

However, when i add the negation jq '.data[] | select(.tags[].id | index( "red" ) | not)' the results are more than strange, with elements’ duplication, totally enigmatic.

How can i use jq to filter the result the way it returns only elements that do not have the exact match among the array values?

>Solution :

index works on an array, your current filter does not pass index to an array, therefore you’re getting other results then expected.


.data[] | select([ .tags[].id ] | index("red") | not)

Here we create an array with all the id’s [ .tags[].id ] and use that array to check for red: | index("red") | not


The above filter gives the following output:

{
  "name": "banana",
  "tags": [
    {
      "id": "yellow"
    },
    {
      "id": "long"
    }
  ]
}
{
  "name": "orange",
  "tags": [
    {
      "id": "orange"
    },
    {
      "id": "round"
    },
    {
      "id": "colored"
    }
  ]
}

Demo


If you want to exclude ‘colored’, use contains():

.data[] | select([ .tags[].id ] | contains(["red"]) | not)
{
  "name": "banana",
  "tags": [
    {
      "id": "yellow"
    },
    {
      "id": "long"
    }
  ]
}

Demo

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading