Looping through an attribute derived from a JSON using Restful sensor

You’re welcome! Always fun to help others succeed.

1 Like

So I thought it was working but it just takes the first game in the json file no matter what the index is set in hassio…

Here is my nhl_stats.yaml that I have in a package folder:

nhl_stats.yaml (16.1 KB)

It shows when there is a No Game but when there is a game no matter the index it shows the content under index 0.

Funny part is even if I replace the {{ states.sensor.nhl_teams_index.attributes.dates[0][“games”][states(‘sensor.nhl_team_index’)|int][“teams”][“home”][“score”] }} with a static number such as 1 it still goes to the first one no matter what, as if it only works with 0.

Seems like it uses

“games”: [
{
“gamePk”: 2018030214,

as a key value for each game. How can I create a value_template that will only extract all the games value under a specific key value

For instance we keep the for loop looking to match the name but then we just keep all the values under the key connected to that particular game rather then the whole json.

ok so if I do:

{{ states.sensor.nhl_teams_index.attributes.dates[0][“games”][ 1 ][“teams”][“home”][“score”] }} it does take the 2nd record rather than the first one.

So something is wrong with:

{{ states.sensor.nhl_teams_index.attributes.dates[0][“games”][ states(‘sensor.nhl_team_index’)|int ][“teams”][“home”][“score”] }}

Anyone knows how to get the json_attributes to work?
Trying to get the attributes derived from my value_template only.

- platform: rest
    resource: https://statsapi.web.nhl.com/api/v1/schedule?startDate=2019-04-06&endDate=2019-04-06&hydrate=linescore
    name: nhl_teams_index
    scan_interval: 
      hours: 24
    value_template: >-
      {% for x in range(value_json.totalGames) %}
        {%  if value_json["dates"][0]["games"][x]["teams"]["home"]["team"]["name"] == states.input_select.nhl_fav_team.state %}
          {{ value_json["dates"][0]["games"][x]["status"]["detailedState"] }}
        {%  elif value_json["dates"][0]["games"][x]["teams"]["away"]["team"]["name"] == states.input_select.nhl_fav_team.state %}
          {{ value_json["dates"][0]["games"][x]["status"]["detailedState"] }}
        {% endif %}
      {% endfor %}
    json_attributes:
      - dates.games.teams.home.team.name
      - dates.games.teams.away.team.name

It’s my understanding that whatever you provide in the list for json_attributes must map directly to unique keys in the supplied JSON list.

So if the JSON list is this:

{ "id":12345, "brand":"Ford", "year":2012, "model":"Focus" }

this would be a valid list for json_attributes:

    value_template: "{{ value_json.id }}"
    json_attributes:
      - brand
      - year
      - model

In your case, this:

    - dates.games.teams.home.team.name

does not map directly to any key contained in the original JSON list.

I don’t have enough experience with JSON attributes to give you concrete solutions. You can experiment and try this to see what, if anything, it produces:

    - dates[0].games[0].teams.home.team.name

I’m not hopeful it will work. Even if it does work you can foresee its limitation (how would you know in advance which index number to specify).

I guess there’s no way since the index is static no matter what I try…

is this the proper syntax:

{% for x in range(states('nhl_game_total_games')) %}

I have this code:

sensor:
  - platform: rest
    resource: https://statsapi.web.nhl.com/api/v1/schedule?hydrate=linescore
    name: nhl_game_total_games
    scan_interval: 
      hours: 24
    value_template: >-
          {{ value_json["totalGames"] | int }}
    json_attributes:
      - dates
      
  - platform: template
    sensors:
      nhl_game_status:
        value_template: >-
          {% for x in range(sensor.nhl_game_total_games | int) %}
            {%  if sensor.nhl_game_total_games.attributes.dates[0]["games"][x]["teams"]["home"]["team"]["name"] == states.input_select.nhl_fav_team.state %}
              {{ sensor.nhl_game_total_games.attributes.dates[0]["games"][x]["status"]["detailedState"] }}
            {% else %}
              No Game
            {% endif %}
          {% endfor %}
        entity_id: sensor.nhl_game_total_games

The rest gives me a value but the sensor nhl_game_status shows as uknown no matter what I tried…

This should be OK if the value is numeric:

{% for x in range(states('sensor.nhl_game_total_games')) %}

otherwise use an int filter:

{% for x in range(states('sensor.nhl_game_total_games')|int) %}

BTW, your example does something different … and it’s invalid:

{% for x in range(sensor.nhl_game_total_games | int) %}

EDIT
Corrected silly mistakes!

Yeah I tried that one as well…

I even did this for now

  nhl_game_status:
    value_template: >-
      {% for a in range(states('nhl_game_total_games')) %}
        {%  if sensor.nhl_game_total_games.attributes.dates[0]["games"][a]["teams"]["home"]["team"]["name"] == states.input_select.nhl_fav_team.state %}
          There is a game
        {% else %}
          No Game
        {% endif %}
      {% endfor %}

But keeps giving “unknown” meaning it never gets into the loop…

My apologies. My previous post had mistakes. I’ve corrected them.

I suggest you use this:

{% for x in range(states('sensor.nhl_game_total_games')|int) %}

There is something wrong with my rest, I tried a simple thing like

  - platform: template
    sensors:
      nhl_game_status:
        value_template: >-
          {{ states.sensor.nhl_game_total_games[0]["games"][0]["status"]["detailedState"] }}
        entity_id: sensor.nhl_game_total_games

And I still get unknown.

OK I did something different:

 - platform: rest
    resource: https://statsapi.web.nhl.com/api/v1/schedule?hydrate=linescore
    name: nhl_game_status
    scan_interval: 
      hours: 24
    value_template: >-
      {% for x in range(value_json.totalGames) %}
        {%  if value_json["dates"][0]["games"][x]["teams"]["home"]["team"]["name"] == states.input_select.nhl_fav_team.state %}
          {{ value_json["dates"][0]["games"][x]["status"]["detailedState"] }}
        {%  elif value_json["dates"][0]["games"][x]["teams"]["away"]["team"]["name"] == states.input_select.nhl_fav_team.state %}
          {{ value_json["dates"][0]["games"][x]["status"]["detailedState"] }}
        {% endif %}
      {% endfor %}
    json_attributes:
      - dates
      - totalGames

How would I write a for loop using that json_attribute: totalGames?

.You may recall that’s what was suggested back in this post.

{% for x in range(value_json.totalGames) %}

This returns the attribute’s value. Try it in the Template Editor to confirm it returns what you expect.

{{ state_attr('sensor.nhl_game_status', 'totalGames') }}

Here’s its used to define the loop range (added an int to ensure the value is numeric):

{% for x in range(state_attr('sensor.nhl_game_status', 'totalGames') | int) %}

Yes but it didn’t work, now I am trying to place the for loop in all the other sensors rather than just the rest sensor like we did previously.

But there is a problem because I don’t think this is a valid code:

{% if states.sensor.nhl_game_status.attributes.dates[0][“games”][x][“teams”][“home”][“team”][“name”] == states.input_select.nhl_fav_team.state %}

unless there is a way to place all the values under the rest sensors json_attributes as such:

json_attributes:
- dates
- totalGames
- dates[0]games[x][teams][home][team][name]

But I don’t think that is possible either…basically I’m stuck :slight_smile:

I agree to both.

Well I hit a roadblock…

Thank you for your help and patience :slight_smile:

If the JSON you are trying to process is too complex for a rest/template sensor, then I’d recommend looking into building a simple custom component.

Can you point in the right direction? Simple custom component (after reading some of the documentation) is huge (much more complex) in comparison to fetching data via REST.

Here is an example that I built a while ago as a custom component. In sensor.py you can see how I fetch XML and then parse it into the sensor’s value and attributes:

Later, I redeveloped this into a more comprehensive component that fetches the same XML and generates multiple entities from the result:

2 Likes