Please help with my code

I want to parse the JSON file from the API where the expiration date is near. here is what I have but it does not work. Also, I am trying to avoid 255 limitation trying to display only expired items.

{
  "data": [
    {
      "expiryDate": "2024-02-10",
      "description": "item 1"
    },
   {
      "expiryDate": "2024-05-10",
      "description": "item 2"
      }
     ]
  }
sensor:
  - platform: rest
    resource: https://some-apilink.com
    name: upcoming_expirations
    headers:
      Authorization: "Bearer somecodehere"
    scan_interval: 14400  # 4 hours
    value_template: >-
      {%- set items = [] %}
      {%- set now = now() %}
      {% for row in value_json.data %}
        {%- set expiry_date = strptime(row.expiryDate, '%Y-%m-%d') %}
        {%- set expiry_date_with_tz = expiry_date.replace(tzinfo=now.tzinfo) %}
        {%- set days_until_expiry = (expiry_date_with_tz - now).days %}
        {%- if 0 <= days_until_expiry <= 30 %}
          {%- set item = row.description + ' expires in ' + (days_until_expiry|string) + ' days' %}
          {%- set items = items + [item] %}
        {%- endif %}
      {% endfor %}
      {{ items | join(', ') if items | length > 0 else 'Nothing expiring in 30 days or less' }}

Can you please help? Even ChatGTP could not help me lol.

Don’t even go there.

Your issue is one of scope: the items variable inside the for loop is not the same as the one outside. Solve this with a namespace:

{%- set ns = namespace(items=[]) %}
{%- set now = now() %}
{% for row in value_json['data'] %}
  {%- set expiry_date = strptime(row.expiryDate, '%Y-%m-%d') %}
  {%- set expiry_date_with_tz = expiry_date.replace(tzinfo=now.tzinfo) %}
  {%- set days_until_expiry = (expiry_date_with_tz - now).days %}
  {%- if 0 <= days_until_expiry <= 30 %}
    {%- set item = row.description + ' expires in ' + (days_until_expiry|string) + ' days' %}
    {%- set ns.items = ns.items + [item] %}
  {%- endif %}
{% endfor %}
{{ ns.items | join(', ') if ns.items | length > 0 else 'Nothing expiring in 30 days or less' }}

thank you very much for your fast reply. Your correction works when I test in the developer tab but when I use it in live API, the home assistant gives a limitation error

Invalid state with length 332. State max length is 255 characters.

This was my problem from the beginning.

You still have too many items then. As per the error message, a state cannot exceed 255 characters.

In case it helps, you can filter without loops:

{{ value_json['data']|selectattr('expiryDate','>=',now().date()|string)|selectattr('expiryDate','<',(now()+timedelta(days=30)).date()|string)|list }}

I get that. Is there any way I can put the output in attributes, not in a state?

You can use json_attributes if you’re using a Rest sensor to pull the data in. More information needed…

You can then use something like the filter above to make a template sensor with filtered attributes.

I don’t know how but thank you I will try to figure it out. Don’t want to bother you any further.