Home > Software design >  find object id when key value in nested array has given string
find object id when key value in nested array has given string

Time:01-30

Input json is:

[
  {
    "id": "00001",
    "profile": {
      "extensions": [
        {
          "name": "/somepath1...../AAAAAA"
        },
        {
          "name": "/somepath2...../xxxxxx"
        }
      ]
    }
  },
  {
    "id": "00002",
    "profile": {
      "extensions": [
        {
          "name": "/somepath1...../zzzzzz"
        },
        {
          "name": "/somepath2...../BBBBBB"
        }
      ]
    }
  },
  {
    "id": "00003",
    "profile": {
      "extensions": [
        {
          "name": "/somepath1...../yyyyyy"
        }
      ]
    }
  },
  {
    "id": "00004",
    "profile": {
      "extensions": []
    }
  }
]

I need to find id of object having .profile.extensions[].name having values containing string AAAAAA or BBBBBB.

Expected output for above json example would be:

00001 AAAAAA 
00002 BBBBBB

Because in the first one the is AAAAAA and in second BBBBBB

CodePudding user response:

You are probably looking for this filter pattern, which iterates over the array elements .[], filters for matching items using select and outputs the field id as raw text due to the -r flag.

jq -r '.[] | select( … ).id'

What the expression within your select filter should be, depends on how you define "having values containing [a] string".

If the search string has to match the last part of a slash-delimited list of substrings (as your sample data might suggest), you could split up the target string using / (or split), extract the last item and use IN to apply the test to a stream of search strings. (Demo)

IN(.profile.extensions[].name / "/" | last; "AAAAAA", "BBBBBB")

If the slashes should not be considered specially (i.e. a search string could also contain slashes) and if a search string simply appearing at the end of the target string is a match, then you can use endswith to test it and any to prevent multiple matches for the same id if several names within the same iterated object end with a given search string. (Demo)

[.profile.extensions[].name | endswith("AAAAAA", "BBBBBB")] | any

If, however, the search string is allowed to appear anywhere in the name, just change endswith to contains. (Demo)

[.profile.extensions[].name | contains("AAAAAA", "BBBBBB")] | any

Regarding your update which altered the output to include the matching search string, and your additional comment stating that the target string is indeed a slash-separated list, the approach now is as follows:

In order to test and output the search string, i.e. to use and to reference it again, we need to store it in a variable (using $s here), which has to happen outside the select filter in order to have its scope reach until the output reference.

jq -r '.[] | ("AAAAAA", "BBBBBB") as $s
  | select(IN(.profile.extensions[].name / "/" | last; $s))
  | "\(.id) \($s)"
'
00001 AAAAAA
00002 BBBBBB

Demo

  •  Tags:  
  • Related