I have a JSON object that looks like this:
[{"name":"NAME_1"},"NAME_2"]
I would like an output of
["NAME_1", "NAME_2"]
Some of the entries in the array are an object with a key "name" and some are just a string of the name. I am trying to extract an array of the names. Using
jq -cr '.[].name // []'
throws an error as it is trying to index .name of the string object. Is there a way to check if it is a string, and if so just use its value instead of .name?
CodePudding user response:
You can use the type
function which returns "object"
for objects.
jq '.[] | if type == "object" then .name else . end' file.json
To get the output as array, just wrap the whole expression into [ ... ]
.
CodePudding user response:
echo '[{"name":"NAME_1"},"NAME_2"]' \
| jq '[ .[] | if (.|type) == "object" then .name else . end ]'
[
"NAME_1"
"NAME_2"
]
Ref:
- https://stedolan.github.io/jq/manual/#ConditionalsandComparisons
- https://stedolan.github.io/jq/manual/#type
As @LéaGris comments, a simpler version
jq '[ .[] | .name? // . ]' file
- https://stedolan.github.io/jq/manual/#ErrorSuppression/OptionalOperator:?
- https://stedolan.github.io/jq/manual/#Alternativeoperator://
CodePudding user response:
Just use the error suppression operator with ?
, map
and scalars
jq 'map( .name?, scalars )'
Note that by using scalars
, it is assumed that other than objects with name
, all others are names of form NAME_*
. If there are other strings as well, and you need to exclude some of them you might need to add some additional logic to do that. e.g. using startswith(..)
with a string of your choice.
map( .name?, select( scalars | startswith("NAME") ) )