Json path filter

I have a rest sensor which returns an array of information. Unfortunatly, the order of the array can change. So id therefore like to add a json filter so I can be sure I get the correct result for my sensor.

I am able to do this for json attributes, usingt the json_attribute_path, however im unsure how to do this for the value_template. Can anyone assist please.

       json_attributes_path: "$.[?(@.id=='BTC')]"
       value_template: '{{ value_json[0].price | round(4) }}'

Thank you

1 Like

Without knowing the exact JSON structure it’s a bit of a guess, but you could try the following as a starting point for your value_template:

{% for x in value_json -%}
{% if x["id"] == "BTC" %}{{ x["price"] | round(4) }}{% endif %}
{%- endfor %}

There is the jinja selectattr that do something similar to your json path : Jinja2 selectattr() Filter - OzNetNerd.com

So , something like

      value_template: '{{ value_json | selectattr("id", "BTC") | map(attribute="price") | list | first | round(4) }}'

An excerpt of the JSON im working with is as follows

[
   {
      "id":"BTC",
      "price":"35304.56229035",
      "rank":"1",
      "high":"63501.99115825",
      "1h":{
         "volume":"2610791622.05",
         "price_change":"638.71365167"
      },
      "1d":{
         "volume":"52050713051.70",
         "price_change":"2349.33767373"
      },
      "7d":{
         "volume":"268063322430.16",
         "price_change":"-2303.07101614"
      },
      "30d":{
         "volume":"1921956719871.83",
         "price_change":"-20838.42231522"
      }
   },
   {
      "id":"ETH",
      "price":"2578.89223662",
      "rank":"2",
      "high":"4164.64375843",
      "1h":{
         "volume":"2347100948.96",
         "price_change":"67.59162043"
      },
      "1d":{
         "volume":"48374522445.23",
         "price_change":"73.26837445"
      },
      "7d":{
         "volume":"290159448480.69",
         "price_change":"-131.05022133"
      },
      "30d":{
         "volume":"1963021260883.43",
         "price_change":"-1397.74974667"
      }
   }
]

As mentioned above, the arrays arent always returned in the same order. So some times ETH may come before BTC for example. (There are about 10 Cryptos im pulling in this rest sensor, this is just a shortened version).

The version of code provided by @exxamalte works, thank you very much.

Unfortunately @koying , ive tried your code in dev tools and it complains that

UndefinedError: No first item, sequence was empty.

I would like to get this jinga selector working however if possible?

Thank you both.

I have managed to get the selectattr to work, but had to use “match” as a test type

{{ value_json | selectattr('id', 'match', 'BTC') | map(attribute='price') | list  | first | round(4)  }} 

Thank you.

3 Likes

you could have used selectattr('id', 'eq', 'BTC') or selectattr('id', '==', 'BTC')

Also, you don’t need to map anything afterwards. You have the object at that point and a map is unnecessary.

{{ (value_json | selectattr('id','eq','BTC') | list | first).price | round(4) }}
3 Likes

EDIT: My JSON data for testing was malformed. Now the syntax works as described!!

Hi!
I tried this today but it doesn’t work for me - I get following error message:

UndefinedError: 'str object' has no attribute 'id'

This is what i entered in Developer Tools - Template:

{% set value_json = {
      "id":"BTC",
      "price":"35304.56229035",
      "rank":"1",
      "high":"63501.99115825",
      "1h":{
         "volume":"2610791622.05",
         "price_change":"638.71365167"
      },
      "1d":{
         "volume":"52050713051.70",
         "price_change":"2349.33767373"
      },
      "7d":{
         "volume":"268063322430.16",
         "price_change":"-2303.07101614"
      },
      "30d":{
         "volume":"1921956719871.83",
         "price_change":"-20838.42231522"
      }
} %}

{{ value_json | selectattr('id', 'match', 'BTC') | map(attribute='price') | list  | first | round(4)  }} 

I‘m on Home Assistant Core 2022.5.4 - does it still work for you?

Many thanks and best regards!