Filtering and transforming output
Ping CLI gives you two ways to filter and reshape command output: the built-in --query flag for JMESPath expressions, and standard Unix pipes to jq for more expressive transformations.
This page covers both tools in depth: when to reach for each, and how to combine them.
|
Both
|
--query and JMESPath
The --query flag evaluates a JMESPath expression against the JSON response before printing it.
Because the expression runs inside Ping CLI, you don’t need to install any additional tools; it works wherever Ping CLI runs.
JMESPath is well-suited for:
-
Extracting a single field or a list of fields from every record.
-
Projecting a subset of fields to reduce noise.
-
Simple equality filters on known values.
Extracting a single field
To get just the name of every environment, project the field across the data array:
pingcli pingone environments list -O json --query 'data[].name'
[
"Policy Change Feature Development",
"Integration Testing",
"Helpdesk Training",
"Sandbox Testing",
"Administrators"
]
Projecting multiple fields
Use a multi-value projection to select a named subset of fields from each record:
pingcli pingone environments list -O json --query 'data[].{id: id, name: name, type: type}'
[
{
"id": "03414408-42f9-4011-b45c-b46c7cc8028b",
"name": "Policy Change Feature Development",
"type": "SANDBOX"
},
{
"id": "5e35b284-e3e4-4b5d-b378-d70674940ac3",
"name": "Helpdesk Training",
"type": "PRODUCTION"
}
]
The keys on the left of : become the output field names, so you can rename fields in the same step.
Accessing nested fields
Use dot notation to reach into nested objects.
For example, to extract the license ID (nested under license.id):
pingcli pingone environments list -O json --query 'data[].{name: name, license: license.id}'
[
{
"name": "Policy Change Feature Development",
"license": "3eb902be-3d37-4926-9c8f-150716e955d3"
},
{
"name": "Helpdesk Training",
"license": "54776175-9a9f-4c21-a4c7-ecb975aa9b56"
}
]
JMESPath and string comparisons
String literals in JMESPath filter expressions must be wrapped in backticks and double-quoted:
pingcli pingone environments list -O json --query 'data[?type==`"PRODUCTION"`].name'
|
The unusual quoting (a backtick-wrapped, double-quoted string) is a requirement of the JMESPath specification, not a shell quirk. When a filter comparison against a string value returns no results, check that you have both the outer backticks and the inner double quotes. |
jq
jq is a standalone JSON processor you pipe output into.
It is more expressive than JMESPath and is the right choice when you need substring matching, sorting, counting, or any transformation that JMESPath cannot express.
If jq is not installed, see the jq download page.
Filtering with select()
Use select() to keep only records that match a condition.
For example, to list only PRODUCTION environments:
pingcli pingone environments list -O json | jq '.data[] | select(.type == "PRODUCTION") | .name'
"Helpdesk Training"
"Terraform Data Protection Test Environment"
"DaVinci Administrators"
"Administrators"
Add the -r flag to strip the surrounding quotes from string output:
pingcli pingone environments list -O json | jq -r '.data[] | select(.type == "PRODUCTION") | .name'
Helpdesk Training
Terraform Data Protection Test Environment
DaVinci Administrators
Administrators
Compound filters
Combine conditions with and and or:
# Sandbox environments whose name contains "Terraform"
pingcli pingone environments list -O json | \
jq -r '.data[] | select(.type == "SANDBOX" and (.name | test("Terraform"))) | .name'
Terraform Test
Terraform Demo
test("pattern") applies a regular expression: use this wherever JMESPath would fall short.
Reshaping records
Build a new object from selected fields using {key: expression} syntax:
pingcli pingone environments list -O json | \
jq '[.data[] | select(.type == "PRODUCTION") | {id, name}]'
[
{
"id": "5e35b284-e3e4-4b5d-b378-d70674940ac3",
"name": "Helpdesk Training"
},
{
"id": "e7e7e106-9547-438c-a30b-0882cb267c10",
"name": "DaVinci Administrators"
},
{
"id": "4c33a4c6-7489-43fe-aa3c-87bd55520427",
"name": "Administrators"
}
]
Wrapping the expression in […] collects results into an array instead of printing them as separate lines.
Counting results
# Count all environments
pingcli pingone environments list -O json | jq '.data | length'
29
# Count production environments only
pingcli pingone environments list -O json | \
jq '[.data[] | select(.type == "PRODUCTION")] | length'
6
Tab-separated output for shell scripts
Use string interpolation to produce tab-separated values you can feed to other shell commands:
pingcli pingone environments list -O json | \
jq -r '.data[] | select(.type == "PRODUCTION") | "\(.name)\t\(.id)"'
Helpdesk Training 5e35b284-e3e4-4b5d-b378-d70674940ac3
Terraform Data Protection Test Environment 0c442e65-9bab-4017-8d44-71fe0c9be286
DaVinci Administrators e7e7e106-9547-438c-a30b-0882cb267c10
Administrators 4c33a4c6-7489-43fe-aa3c-87bd55520427
Filtering ndjson
Both --query and jq work with ndjson, but the expression targets a single record rather than an array.
With bare -O ndjson, each line is a raw record with no envelope wrapper.
Reference fields directly: do not use data. prefix:
# Print only the name field from every record
pingcli pingone environments list -O ndjson --query 'name'
With jq, use select() directly on the stream (jq processes each line independently):
pingcli pingone environments list -O ndjson | \
jq -r 'select(.type == "PRODUCTION") | .name'
Helpdesk Training
Terraform Data Protection Test Environment
DaVinci Administrators
Administrators
If you need envelope fields (such as status or meta) alongside each record, use -O ndjson-wrapped instead.
With ndjson-wrapped, records are wrapped in the full envelope and field access uses .data.name, .data.type, and so on:
pingcli pingone environments list -O ndjson-wrapped | \
jq -r 'select(.data.type == "PRODUCTION") | .data.name'
Choosing between --query and jq
Need |
Use |
Why |
Extract or project fields |
|
Zero dependencies; shorter command line |
Equality filter on a known value |
|
Straightforward; works without installing |
Substring or regex match |
|
JMESPath has no |
Sort, count, or aggregate |
|
JMESPath does not support these operations |
Compute derived fields or reshape output significantly |
|
|
Process one record at a time in a shell loop |
|
No need to parse a full JSON document; loop with |