Json template sensor issue

Hello.
My openmqttgateway compiled in pilight mode return json string (with weather stations data). Еach station has its own id, and I need to separate them into different sensors. So so i need to use templates. But I got an unexpected issuе, when debug my template in dev->template:

-1-
{% set val = states('sensor.gatewaypilight') %}
{{ val }}
-2-
{{ val.id }}
-3-
{% set val = {'id': 159, 'temperature': 23.5, 'humidity': 55.0, 'battery': 1} %}
{{ val }}
-4-
{{ val.id }}

And output:

-1-

{'id': 159, 'temperature': 23.5, 'humidity': 55.0, 'battery': 1}
-2-

-3-

{'id': 159, 'temperature': 23.5, 'humidity': 55.0, 'battery': 1}
-4-
159

So, I dn’t understand, why in step 2 I have empty value in val.id

Take a look at this topic.

The post referenced by @VDRainer probably tells you what you need to know. To answer your exact question, though:

Two things:

Firstly, you need to use the from_json filter to interpret the sensor’s state as JSON rather than a string (docs), so

{{ (val|from_json).id }}

Also, I’d be careful with keys like id that might well be an underlying property of the HA definition of a sensor. To guard against this, use this type of lookup instead:

{{ (val|from_json)["id"] }}

Thanks for the answer. I saw this topic and will do as it is written there, but my issue is a little different.

Yes, I tried these options too, and got the error for both cases:

Error rendering template: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)

Really? I have only one sensor returning JSON:

image

and this in the template editor:

{% set val = states('sensor.camera_status') %}
1. {{ val }}
2. {{ val.bv }}
3. {{ val["bv"] }}
4. {{ val|from_json }}
5. {{ (val|from_json).bv }}
6. {{ (val|from_json)["bv"] }}

renders as this:

1. {"bt": 31.6, "bv": 4.171}
2. 
3. 
4. {'bt': 31.6, 'bv': 4.171}
5. 4.171
6. 4.171

from_json won’t work because it’s not json. It’s a string representation of a dictionary. Json would require all strings to be wrapped in ".

@zavant Welcome to the community!

If you are using MQTT, I recommend adjusting the sensor.

Otherwise replace ' with " then convert use from_json.

{% set val = states('sensor.gatewaypilight').replace("'", '"') | from_json %}
1 Like

I was faced with a similar situation recently and I used the replace("'", '"') technique but then pnbruckner suggested that I simply use to_json like this:

{% set val = states('sensor.gatewaypilight') | to_json %}

@zavant

Try the to_json filter, as shown here, and let us know if it works for you.

EDIT
My mistake. The use of to_json doesn’t apply here.

Great!! It’s works. Thank you very much!

The Jinja2 interpreter used by the Template Editor is lax about what it considers to be “proper JSON”. It readily accepts single-quotes within a dictionary. However, the JSON parser used for Template Sensors is strict and rejects the use of single quotes. That means a template that handles “single-quoted JSON” in the Template Editor is likely to fail when used in a Template Sensor (if supplied with “single-quoted JSON”).

1 Like

That’s not true. It’s the same code. The reason his worked is because it’s json.

Try it yourself with strings:

{% set foo = "{'a':1}" %}
{% set bar = foo | to_json %}
{{ bar.a }}
{% set bar = foo.replace("'",'"') | from_json %}
{{ bar.a }}
{% set bar = foo | from_json %} #ERRORS

Sorry, you lost me; not sure what’s “not true”. What I know is:

  • to_json worked for me when I used it in a script to convert stringified JSON
  • a Template Sensor fed single-quoted JSON is an unhappy Template Sensor

This is what I was referring to. I can’t quote the whole response because the site auto removes whole response quoting.

In the Template Editor, it accepts either single or double-quotes within a JSON dictionary. It’s been my experience that Template Sensors fed single-quoted JSON aren’t so accommodating.

yeah, because those are dictionaries. Dictionary != string that represents a dictionary converted to JSON.

To clarify, the difference is:

Dictionary as string

{% set foo = "{'a':1}" %}

vs

Dictionary

{% set foo = {'a': 1} %}

You’ll always get Dictionary as string from states.

Yes, I understand that when the Template Sensor receives the stringified JSON payload it converts it to a JSON dictionary … and if the stringified JSON uses single-quotes, the conversion process throws an error.

In retrospect my use of the word “lax” was misleading. If you’re defining a JSON dictionary in the Template Editor, it accepts either single or double-quotes. It’s the conversion process, from stringified JSON to JSON, that wants to see double-quotes. So when someone use the Template Editor to experiment with JSON dictionaries (not stringified but a proper dictionary) they may be led to believe that single-quotes are fair-game until they actually try feeding that format (stringified JSON) through the conversion process.

Right, but maybe you were missing the fact that OP was grabbing the value dictionary from a state meaning its a string… Which is why to_json will not work as well as any of the templating attempts in the thread aside from wrapping the attempts in quotes to make it a string.

1 Like

Gotcha, yes, you’re right, I overlooked that key point. I proved it to myself by publishing two different payloads to an MQTT Sensor:

'{"a": 1}'

"{'a': 1}"

The first case, using double-quotes, is correctly converted by from_json (as per my description of the conversion process):

The second case, using single-quotes, fails to be converted by from_json (as expected):


Neither form of these strings benefits from the use of the to_json filter


I’ve retracted my initial suggestion (in my initial post) to use to_json.