如何用jq在JSON任意层级查找指定值并获取对应父键logId
在未知层级JSON中查找特定值并返回对应logId的jq解决方案
问题背景
需求:在结构未知的JSON任意层级中查找特定值(无需关注键名),并返回该值所在条目对应的上层父键logId。
已实现的目标值定位命令:
cat /tmp/test.json | jq '.auditLogs[] | .. | .credentialId? | select(. == "CREDENTIALS_VAULT-1212121212121")'
遇到的问题:尝试通过变量关联logId时,执行以下命令返回多个重复结果:
cat /tmp/test.json | jq '.auditLogs[] as $parent | .. | .credentialId? | select(. == "CREDENTIALS_VAULT-1212121212121") | $parent | {"logId":.logId}'
测试JSON示例:
{ "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 } ] } ] }
解决方案及解释
问题根源
原命令中..递归遍历会经过目标值所在路径的所有父节点,每遍历到一个节点都会触发一次$parent输出,导致同一个logId被重复返回。
正确命令1(高效推荐)
直接对每个auditLogs条目判断是否包含目标值,匹配则输出一次logId:
# 若明确知道目标值对应的键名是credentialId cat /tmp/test.json | jq '.auditLogs[] | select(.. | .credentialId? == "CREDENTIALS_VAULT-1212121212121") | .logId' # 通用版本(不限制键名,任意层级匹配目标值) cat /tmp/test.json | jq '.auditLogs[] | select(.. | . == "CREDENTIALS_VAULT-1212121212121") | .logId'
正确命令2(去重方式)
如果要保留原递归查找逻辑,可通过unique去重:
cat /tmp/test.json | jq '.auditLogs[] as $parent | .. | .credentialId? | select(. == "CREDENTIALS_VAULT-1212121212121") | $parent.logId | unique'
测试结果
执行推荐命令后,会返回唯一符合条件的logId:
"169807591200060002"
内容的提问来源于stack exchange,提问作者mackermann
相关产品推荐
相关产品推荐

