Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jq select objects that have specific value in nested json bash

Tags:

json

bash

jq

this is my json.

[
 {
  "time": "2017-06-10 00:00:48-0400,317",
  "UserInfo": {
    "AppId": "ONE_SEARCH",
    "UsageGroupId": "92600",
   },
  "Items": [
    {
     "PublicationCode": "",
     "OpenUrlRefId": "",
     "ReferringUrl": "N",
     "OpenAccess": "0",
     "ItmId": "1328515516"
    }
   ]
 },
 {
  "time": "2017-06-10 00:00:48-0400,548",
  "UserInfo": {
    "AppId": "DIALOG",
    "UsageGroupId": "1195735",
  },
  "Items": [
    {
     "Origin": "Alert",
     "PublicationCode": "",
     "NumberOfCopies": 1,
     "ItmId": "1907446549"
    },
    {
     "Origin": "Alert",
     "PublicationCode": "",
     "NumberOfCopies": 1,
     "ItmId": "1907446950",
    }
  ]
 }
]

I want use jq to extract the object that have "Origin": "Alert" in its element "Items". And the result should looks like this:

{
 "time": "2017-06-10 00:00:48-0400,548",
 "UserInfo": {
   "AppId": "DIALOG",
   "UsageGroupId": "1195735",
},
 "Items": [
   {
    "Origin": "Alert",
    "PublicationCode": "",
    "NumberOfCopies": 1,
    "ItmId": "1907446549"
   },
   {
    "Origin": "Alert",
    "PublicationCode": "",
    "NumberOfCopies": 1,
    "ItmId": "1907446950",
   }
 ]
}

Or this:

{
 "Items": [
    {
     "Origin": "Alert",
     "PublicationCode": "",
     "NumberOfCopies": 1,
     "ItmId": "1907446549",
     "ReasonCode": ""
    },
    {
     "Origin": "Alert",
     "PublicationCode": "",
     "NumberOfCopies": 1,
     "ItmId": "1907446950",
    }
 ]
}

How to do it by using jq? I have tried several ways but most of them will just return an array with all children objects that include "Origin":"Alert". I need these children objects still keep there structure, because I need to know which of them happened together and which of them happened separately.

BTW, the only value of "Origin" is "Alert". So if you have any method to select an object with a given key name, it should also work.

Thank you! :)

like image 229
Eleanor Avatar asked Jun 29 '17 18:06

Eleanor


1 Answers

The filter:

.[] | select( any(.Items[]; .Origin == "Alert"))

produces the first-mentioned admissible result. If your jq does not have any/2 then I'd suggest upgrading. If that's not an option, then you could use the following simple but rather inefficient filter instead:

.[] | select( .Items | map(.Origin) | index("Alert"))

Or:

.[] | select(reduce .Items[] as $item (false; . or ($item | .Origin == "Alert")))
like image 125
peak Avatar answered Nov 09 '22 20:11

peak