Extract value from json

same error.
You can use
{% set my_test_json = [ { “cmd” : “GetMdState”, “code” : 0, “value” : { “state” : 0 } } ] %}
{{ my_test_json.[2].[0] }}

is you want to try a few things.

1 Like

Got it.

{{ my_test_json.0.value.state }}

It was the top level list ‘[…]’ stuffing it up.

1 Like

f’k me! I swear I have been screwing around for f’king HOURS

1 Like

Always handy to have an extra pair of eyes. This place is great for that.

1 Like

Also tried removing the [ and ] with replace but doesn’t work. Also tried string…
nope.

This is eerily familiar:

The string is coming from here:

  - platform: rest
    resource: http://192.168.1.44/api.cgi?cmd=GetMdState&user=admin&password=xxxxx
    name: motion_test

@pnbruckner @petro feel free to weigh in.

Try this:

{{ states('sensor.motion.test') |regex_findall_index('\d', index=1) }}

Tom’s solution will always get the 2nd digit, I.E. The digit after the word state. If the shape of the object changes, that won’t work. If you wan’t to ensure that you always get the state…

{% set value = my_test_json | regex_findall_index('\"state\" : \d+', index=0) %}
{{ value.split(':')[-1].strip() }}

This is finding the first instance of the phrase "state" : <number>. Then, we split the returned value on the colon. Select the last value (the number), and remove the extra white space.

EDIT: This of course assumes that the state is a string. If you change your rest sensor… you can have it just plop out that value.

  - platform: rest
    resource: http://192.168.1.44/api.cgi?cmd=GetMdState&user=admin&password=xxxxx
    name: motion_test
    value_template: "{{ value_json[0].value.state }}"
    json_attributes:
      - 0

This should put the whole object as a 0 attribute. Don’t know if that portion will work, never tried it. If it does work, your attributes will be accessible as json object too.

Last EDIT: I think we need a PR that depreciates json_attributes and replaces it with json_attributes_template, like MQTT sensors. There are too many of these topics that return a list of objects and that would require a template to extract.

1 Like

Thanks @petro
Is there a way I can make the rest sensor write the whole text string like a normal rest sensor rather than just that one attribute?

don’t think so, that’s why we need an update to json_attributes as a template.

What I don’t understand… in Tom’s example he used index 1 and you use index 0 - this is very fuzzy… both work but I’m not 100% sure I understand why… (well I’m 100% sure I don’t understand actually)

What if I wanted the value of the cmd or code?

Because my expression was very sloppy and returned 2 results. Petro’s regex is more exact and will only return one result.

hmm… ok… what if I want the value of “cmd” - even from the docs I don’t understand what the regex_findall_index is doing

FWIW, you can use a capturing group within the regex pattern to pluck out the desired value directly.

{{ my_test_json | regex_findall_index('\"state\" : (\d+)')  }}

The regex pattern is:

  • \"
    escape the meaning of a double-quote and match it
  • state
    match the literal word state
  • \"
    escape the meaning of a double-quote and match it
  • :
    match literal space followed by a colon followed by another space
  • (\d+)
    everything matched within the parentheses will be captured. The pattern within the parentheses will match one or more digits.

So if fed a string like this:

blablabla"state" : 12345abcdefg

it will return 12345

When given your example, it returns 0 as shown in the following screenshot from regex101.com

1 Like

so \d+ means it’s looking for digits? what if I wanted text? like the value of “cmd”?

just saw your edit… I’ll play on that site there! thanks.

{{ my_test_json | regex_findall_index(\"cmd\" : \"(\w+)\"')  }}

1 Like

so where does the index come into it in Tom’s and Petro’s examples? seems to not need it?

The default is to return the zeroth index (i.e. numerically first matching result).

If the capturing group were to find multiple matches, it will return a list of them. Then you need to specify index to indicate which one you want.

In this example, the capturing group returns three matches:

If I wanted the second result in the list (bat) I need to indicate index=1 (the list is zero-based so 0, 1, 2, 3, etc).

{{ my_test_json | regex_findall_index('\"state\" : (\d+)', index=1)  }}
1 Like

ahhhhh so in Tom’e one the first digit would be the “code” and the second, index=1 would be “state” which is why Petro’s example is better. What was doing my head in in Tom’s one was nowhere did he specify state but now it’s clicking into place.

Thanks Taras!

1 Like

Did you try the json attributes field in the rest sensor? That would make this a ton easier if it works.