skip to Main Content

I would like to find in a JSON file a specific value (without worrying about the key) at any level of my JSON file (I don’t know in advance the exact tree) and display the parent keys.

I have extracted this sample :

cat /tmp/test.json | jq
{
  "totalCount": 2,
  "pageSize": 1000,
  "auditLogs": [
    {
      "logId": "169807591200060002",
      "eventType": "CREATE",
      "category": "CONFIG",
      "entityId": "HTTP_CHECK-12121212121212",
      "timestamp": 1698075912003,
      "success": true,
      "patch": [
        {
          "op": "replace",
          "path": "/",
          "value": {
            "steps": [
              {
                "id": {
                  "type": "HTTP_CHECK_STEP"
                },
                "requestType": "OAUTH2",
                "destinationUrl": "https://www.mywebsite.com",
                "httpMethod": "POST",
                "acceptAnyCertificate": true,
                "followRedirects": true,
                "displayName": "My Website",
                "userAgent": "",
                "httpCheckHeaders": [
                  {
                    "name": "Content-Type",
                    "value": "application/x-www-form-urlencoded"
                  }
                ],
                "stepPerformanceThreshold": 0,
                "requestBody": null,
                "constraints": [
                  {
                    "constraintType": "HttpStatusesList",
                    "passIfFound": false,
                    "pattern": ">=400"
                  }
                ],
                "preScript": "",
                "postScript": "",
                "attributes": {
                  "oAuth2RequestId": "1",
                  "oAuth2BodyInputType": "RAW",
                  "oAuth2addAuthDataTo": "REQUEST_BODY"
                },
                "postExecutionScriptVariables": [
                  "{bearerToken-1}"
                ],
                "preExecutionScriptVariables": [],
                "certificateId": "",
                "basicAuthId": "",
                "certStoreId": 0,
                "basicAuthStoreId": 0,
                "authenticationConfig": {
                  "type": "BASIC_AUTHENTICATION",
                  "realmName": null,
                  "kdcIp": null,
                  "credentialId": "CREDENTIALS_VAULT-1212121212121"
                },
                "executionProperties": {},
                "shouldNotPersistSensitiveData": true
              }
            ],
            "publicLocationIds": [
              124
            ],
            "userModificationTimestamp": 1698075911987,
            "customProperties": [],
            "version": 6
          },
          "oldValue": null
        }
      ]
    },
    {
      "logId": "169807591200060001",
      "eventType": "CREATE",
      "category": "CONFIG",
      "entityId": "HTTP_CHECK-12121212121212",
      "environmentId": "b416bf43-a9d2-4123-aa70-e36ff39c0ad9",
      "timestamp": 1698075911986,
      "success": true,
      "patch": [
        {
          "op": "replace",
          "path": "/",
          "value": {
            "frequency (Frequency)": 0,
            "locations": [
              {
                "location (Location)": "SYNTHETIC_LOCATION-000000000000007C"
              }
            ]
          },
          "oldValue": null
        }
      ]
    }
  ]
}

I am able to find the string "CREDENTIALS_VAULT-1212121212121" with this recursive command :

cat /tmp/test.json | jq '.auditLogs[] | .. | .credentialId? | select(. == "CREDENTIALS_VAULT-1212121212121")'                       
"CREDENTIALS_VAULT-1212121212121"

But I would like also to get the parent key "logId" at the first level. I tried to use a variable ($parent) but unfortunately I got several results instead of only one :

cat /tmp/test.json | jq '.auditLogs[] as $parent | .. | .credentialId? | select(. == "CREDENTIALS_VAULT-1212121212121") | $parent | {"logId":.logId}'
{
  "logId": "169807591200060002"
}
{
  "logId": "169807591200060001"
}

Does anyone have an idea for this need?

2

Answers


  1. You could use paths to find the paths with matching values, extract from it the first two items (["auditLogs",0] in this case), use getpath to retrieve that object, and extract .logId from there:

    jq -r 'getpath(paths(. == "CREDENTIALS_VAULT-1212121212121")[:2]).logId'
    
    169807591200060002
    

    Demo

    If you want objects containing only the logId field, use {logId} instead:

    jq 'getpath(paths(. == "CREDENTIALS_VAULT-1212121212121")[:2]) | {logId}'
    
    {
      "logId": "169807591200060002"
    }
    

    Demo

    You can also consider collecting the results in an array by wrapping […] around the filter. Or use the --arg option to import the search key from the command line, etc.

    Login or Signup to reply.
  2. You can use IN (or any(stream; condition)):

    .auditLogs[]
    | select(IN(.. | .credentialId?; "CREDENTIALS_VAULT-1212121212121"))
    | .logId
    

    or, depending on your output format requirements:

    .auditLogs[]
    | select(IN(.. | .credentialId?; "CREDENTIALS_VAULT-1212121212121"))
    | { logId }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search