I have the following json data:
{"results":
{"xxxxxx":{"id":"as23","status":1,"res":"xsd"},
{"xxxxxx":{"id":"fds34","status":2,"res":"dox"},
{"xxxxxx":{"id":"as23","status":1,"res":"kog"},
{"xxxxxx":{"id":"dgs5","status":2,"res":"dox"},
{"xxxxxx":{"id":"as23","status":2,"res":"dox"},
{"xxxxxx":{"id":"as23","status":1,"res":"dox"}
The list is very long, but you get the idea. What I want, is to look up for every object containing the id as23
, and count how many of them have the status 1
.
So, I am using this in HomeAssistant as a rest sensor, and my filter expression looks like this:
{{ value_json.results|selectattr("id", "==", "as23")|selectattr("status", "eq", 1)|list|length }}
My issue is: I don't know what the value of xxxxxx
are, and they can differ, and still contain the id as23
.
How to achieve this?
CodePudding user response:
Assuming a correct version of your JSON that would be:
{
"results":[
{
"xxxxxx":{
"id":"as23",
"status":1,
"res":"xsd"
}
},
{
"xxxxxx":{
"id":"fds34",
"status":2,
"res":"dox"
}
},
{
"xxxxxx":{
"id":"as23",
"status":1,
"res":"kog"
}
},
{
"xxxxxx":{
"id":"dgs5",
"status":2,
"res":"dox"
}
},
{
"xxxxxx":{
"id":"as23",
"status":2,
"res":"dox"
}
},
{
"xxxxxx":{
"id":"as23",
"status":1,
"res":"dox"
}
}
]
}
Your requirement can be easily achieved with the help of the filter json_query
and the JMESPath query language, that help you achieve wildcards on properties.
Given the debug task:
- debug:
var: >-
value_json | json_query(
'length(results[].*[] | [?id == `as23` && status == `1`])'
)
This would yield the expected:
ok: [localhost] =>
? |-
value_json | json_query(
'length(results[].*[] | [?id == `as23` && status == `1`])'
)
: '3'
CodePudding user response:
Building up on @β.εηοιτ.βε's answer, this can be achieved without json_query
(in case you don't want to / can't pip install jmespath
) using only core functions.
Using the same assumed correct json structure as in @β.εηοιτ.βε's answer, the following task:
- debug:
msg: "{{
value_json.results |
map('dict2items') |
map('map', attribute='value') |
flatten |
selectattr('id', '==', 'as23') |
selectattr('status', '==', 1)
}}"
Gives:
TASK [debug] ***************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": [
{
"id": "as23",
"res": "xsd",
"status": 1
},
{
"id": "as23",
"res": "kog",
"status": 1
},
{
"id": "as23",
"res": "dox",
"status": 1
}
]
}