Templating Help: Extracting from list/array

I have been struggling to develop a template to extract a list of items that are nested in an array (I am not sure if this is the fully correct terminology).

I would ultimately like to display a list of addon names that have pending updates for display in markdown, either in notifications or in lovelace (Something like this example, but this specifically does not work because the items are in an array). I would also like to better understand templating, and how to extract listed information, for other purposes.

The new-ish sensor.supervisor_updates has an attribute addons that is an array (correct term?) of addons with updates. I am able to get one addon name from the list, but am struggling with the for logic, as will as with json & yaml object lists.

Here is an example of the data that is attempting to be parsed, using template example:
{{state_attr('sensor.supervisor_updates','addons')}}

[{"name":"Grocy","slug":"a0d7b954_grocy","description":"ERP beyond your fridge! A groceries & household management solution for your home","state":"started","version":"0.16.0","version_latest":"0.17.0","update_available":true,"repository":"a0d7b954","icon":true,"logo":true},{"name":"Grafana","slug":"a0d7b954_grafana","description":"The open platform for beautiful analytics and monitoring","state":"started","version":"7.5.1","version_latest":"7.5.2","update_available":true,"repository":"a0d7b954","icon":true,"logo":true},{"name":"ESPHome","slug":"a0d7b954_esphome","description":"ESPHome add-on for intelligently managing all your ESP8266/ESP32 devices","state":"started","version":"2022.3.0","version_latest":"2022.3.1","update_available":true,"repository":"a0d7b954","icon":true,"logo":true}]

The template below will return the name of the first addon:

{% set addon_update = state_attr('sensor.supervisor_updates','addons') %}
{% set addon_update_list = addon_update[0]["name"] %}
{{addon_update_list}}

This returns the second:

{% set addon_update = state_attr('sensor.supervisor_updates','addons') %}
{% set addon_update_list = addon_update[1]["name"] %}
{{addon_update_list}}

From here I cannot get the right syntax. How do I iterate the [0] path? I have tried many options and referred to many other posts, with no luck.

{% set addon_update = state_attr('sensor.supervisor_updates','addons') %}
{% set i = 0 %}
{% for addon_update_list in addon_update[i]['name'] %}
{{addon_update_list}}
{% set i = i+1 %}
{% endfor %}

Any help would be greatly appreciated. Do I need a filter? do I need an if expression?

Thanks @123! That gives me a comma separated list off the addons, which is certainly better than anything I had. I did not know about |map, so I’ll have to research that more.

Is there a way to have that filter display as a bulleted list in markdown (similar to this example):

I think I was looking at the for looping so that I could expand what is possible after I learned how to extract a name of the addon. Such as linking to changelog, adding version info, etc.

Thank you for the additional suggestion. Would that still have the same issue adding context such as “Grocy 0.16.0 → 0.17.0”. I feel like using the map and regex is less flexible than a loop. Is that not possible?

The “join” is what is turning the list (array) into a string. If you want to loop them yourself, you could do something like:

{%- set loop_this =  state_attr('sensor.supervisor_updates', 'addons') | map(attribute='name')  -%}
{%- for this_item in loop_this -%}
do whatever with {{ this_item }}
{%- endfor -%}

It achieved everything you had requested in a single line (and is capable of doing more).

I normally look for shorter ways to get a desired result, not longer ways. I’ve removed my suggestions so your topic can focus exclusively on solving it the way you prefer (with a for-loop). Good luck.

I’ve tried the information shared here and in some other places on a similar challenge but am not quite there. I’ve created a rest sensor to extract moon phase data from the US Naval Observatory (https://aa.usno.navy.mil/api/moon/phases/year?year=2024). I’m trying to find a way to narrow this down to a specific month or day of month. How can I narrow down this array to only show the data where month = 1 and day = 4 for example? Ultimately, I want to take this and compare today’s date with this and show the next indicated moon phase, and when it will occur.

{
“apiversion”: “4.0.1”,
“numphases”: 50,
“phasedata”: [
{
“day”: 4,
“month”: 1,
“phase”: “Last Quarter”,
“time”: “03:30”,
“year”: 2024
},
{
“day”: 11,
“month”: 1,
“phase”: “New Moon”,
“time”: “11:57”,
“year”: 2024
},
{
“day”: 18,
“month”: 1,
“phase”: “First Quarter”,
“time”: “03:52”,
“year”: 2024
},
{
“day”: 25,
“month”: 1,
“phase”: “Full Moon”,
“time”: “17:54”,
“year”: 2024
},
{
“day”: 2,
“month”: 2,
“phase”: “Last Quarter”,
“time”: “23:18”,
“year”: 2024
},
{
“day”: 9,
“month”: 2,
“phase”: “New Moon”,
“time”: “22:59”,
“year”: 2024
},
{
“day”: 16,
“month”: 2,
“phase”: “First Quarter”,
“time”: “15:01”,
“year”: 2024
},
{
“day”: 24,
“month”: 2,
“phase”: “Full Moon”,
“time”: “12:30”,
“year”: 2024
}

{{ value_json.phasedata | selectattr('day', 'eq', 4)
| selectattr('month', 'eq', 1) | list 
| map(attribute='phase') | first }}

You can use the following to get the dictionary for the next phase event:

{% set events = value_json.phasedata %}
{% set (now_m, now_d) = (now().month, now().day) %}
{% set this_event = events | selectattr('month', 'eq', now_m) 
| selectattr('day', 'ge', now_d) | sort(attribute = 'day') | first  %}
{{ this_event if this_event is defined else events 
| selectattr('month', 'eq', now_m+1) | sort(attribute = 'day') | first }}

I have a sensor that’s pulling in the json data called sensor.annual_moon_phase_data. Do I replace “value_json.phasedata” with “states.sensor.annual_moon_phase_data.phasedata?”

Probably not… are you really storing it in the state or in an attribute?

States are always strings so you would need to use from_json to get a functional list… However, states are limited to 255 characters, so it would never contain all the necessary data.

Attributes can be other data types, so you will need to let us know which type the attribute is for us to give you an accurate answer.

I created a rest sensor below. If that’s not the best way of getting the data, I can change it but it looks like it’s pulling in and saving in the entire year.

- platform: rest
  name: Annual Moon Phase Dates
  unique_id: annual_moon_phase_dates_times
  resource_template: "https://aa.usno.navy.mil/api/moon/phases/year?year={{now().year}}&tz=-5&dst=true"
  method: GET
  value_template: "{{ value_json.moon_phase_dates }}"
  json_attributes:
   - phasedata
  scan_interval: 3600 

Ok, so it’s in the attribute phasedata as a true array. In that case you would replace value_json.phasedata in my templates above with state_attr('sensor.annual_moon_phase_dates', 'phasedata') :

Phase at specific day and month:
{{ state_attr('sensor.annual_moon_phase_dates', 'phasedata') 
| selectattr('day', 'eq', 4)
| selectattr('month', 'eq', 1)
| list | map(attribute='phase') | first }}

Next Phase event dictionary:
{% set events = state_attr('sensor.annual_moon_phase_dates', 'phasedata') %}
{% set (now_m, now_d) = (now().month, now().day) %}
{% set this_event = events | selectattr('month', 'eq', now_m) 
| selectattr('day', 'ge', now_d) | sort(attribute = 'day') | first  %}
{{ this_event if this_event is defined else events 
| selectattr('month', 'eq', now_m+1) | sort(attribute = 'day') | first }}

Keep in mind that the “Next Phase” template will fail between the day after the last event in December and New Year’s day.

Works perfectly! Thanks for the guidance.