Help needed parsing JSON from Todo list

Hi, I've been banging my head for a couple of hours now, trying to parse the data from the JSON response from todo.get_items.

Background: I have a to-do list for my exercise routine, with a To Do for each day which contains a markup-based description. (It's actually stored in Google Tasks but I don't think that matters). I'm trying to create a markup card which shows only today's exercise, but I'm struggling to get the data out in a usable format.

The todo.get_items response comes back in the following format

{
  "todo.exercise": {
    "items": [
      {
        "summary": "Monday: Steps",
        "uid": "RmdwakV4bVp2UjJTNkxNUA",
        "status": "needs_action",
        "due": "2026-06-15",
        "description": "![Image](http://homeassistant.local:8123/local/dashboard-elements/Exercise-Steps.jpg)\n15min+ Steps"
      }
}

(there's an entry each day of the week but I've just shown the first

I'm trying to create a sensor "today's exercise" that would have state=done or not, and attributes activity="Steps",description, and use this to populate a Markup card.

I've got as far as extracting the object for today's exercise by exact match:

{% set action_response = {"todo.exercise":{"items":[{"summary":"Monday: Steps","uid":"RmdwakV4bVp2UjJTNkxNUA","status":"needs_action","due":"2026-06-15","description":"![Image](http://homeassistant.local:8123/local/dashboard-elements/Exercise-Steps.jpg)\n15min+ Steps"},{"summary":"Sunday: Stretch and Measure","uid":"RW5XcGpUNDlpOWRlYmJGbw","status":"needs_action","due":"2026-06-14","description":"![Image](http://homeassistant.local:8123/local/dashboard-elements/Exercise-Weight.jpg)\n1. Measure Weight\n2. Measure Blood Pressure occasionally"},{"summary":"Saturday: Run or other Cardio","uid":"bFRQRDJvZVBGaWU4cXVQUg","status":"needs_action","due":"2026-06-13","description":"![Image](http://homeassistant.local:8123/local/dashboard-elements/Exercise-Running.jpg)"},{"summary":"Friday: Wii Yoga, Stretch or Catch-up","uid":"TW1yaWM3a3RSN0otRThaRQ","status":"needs_action","due":"2026-07-10","description":"![Image](http://homeassistant.local:8123/local/dashboard-elements/Exercise-Stretch.jpg)"},{"summary":"Thursday: Core Strength","uid":"WFJiWUJBSUJHRzlDa1FQNA","status":"needs_action","due":"2026-06-11","description":"![Image](http://homeassistant.local:8123/local/dashboard-elements/Exercise-Core.jpg)\n1. Weighted waist bend\n2. Side Bend\n3. Squat\n4. Sit-ups\n5. Heel Raise\n6. Glute Bridge (lie on back, calves vertical, raise butt)"},{"summary":"Wednesday: Run","uid":"VDhhcFR4QmhZWDlUZGgyZQ","status":"completed","due":"2026-06-10","description":"![Image](http://homeassistant.local:8123/local/dashboard-elements/Exercise-Running.jpg)\n\nRun at least 15min/2Km","completed":"2026-06-10T11:39:10.468000+00:00"},{"summary":"Tuesday: Upper Body Strength","uid":"SjVNZENjQ0FKOFVlM0tIVA","status":"completed","due":"2026-06-09","description":"![Image](http://homeassistant.local:8123/local/dashboard-elements/Exercise-Upper.jpeg)\n1. Bicep Curl\n2. Shoulder Fly\n3. Shrug\n4. Tricep Curl (!)\n5. Lateral Lift\n6. Pressup or chest resistance band\n7. *Shoulder Lift* (!!)\n","completed":"2026-06-09T17:39:24.937000+00:00"}]}} %}
{{ action_response['todo.exercise']['items']  | selectattr('summary','eq','Monday: Steps') | list   }}

Which gives me

[{'summary': 'Monday: Steps', 'uid': 'RmdwakV4bVp2UjJTNkxNUA', 'status': 'needs_action', 'due': '2026-06-15', 'description': '![Image](http://homeassistant.local:8123/local/dashboard-elements/Exercise-Steps.jpg)\n15min+ Steps'}]

But I can't figure out how to do a partial match on the 'summary' field. If I could do the following that would be lovely selectattr('summary','startswith','Monday:') but this isn't an operator so I guess I need to do something much more complicated.

Is there a straightforward way to do this? Or should I simplify the data to match my limited JSON/Jinja2 skills?

Or, alternatively, is there a custom To Do List card that offers more flexibility than the built-in one and would help me with this?

Thanks, Home Assistant hive mind!

Use search instead of eq in selectattr.

search accepts regex patterns.

Example

String must start with Monday:

selectattr('summary','search','^Monday')

If you want to avoid regex for this particular application, use match (it always starts its search from the beginning of the string). Effectively, it's like startswith

selectattr('summary','match','Monday')

Thanks Taras, that did the trick. I had looked at the Jinja2 reference but hadn't realised there were these Home Assistant extensions.

For anyone who comes across this thread looking for how to create sensors based on todo items, here's the final code of the sensors for today's exercise. It would be nice if there were a way to avoid repeating the line set exercise_today but again that's beyond my skills.

  - trigger:
      - trigger: time_pattern
        minutes: /15
    action:
      - action: todo.get_items
        data:
          status:
            - needs_action
            - completed
        target:
          entity_id: todo.exercise
        response_variable: exercise_list
    sensor:
      - name: "Today's Exercise"
        unique_id: todays_exercise
        # Finds the to do list entry that starts with today's date
        state: >-
          {% set exercise_today = (exercise_list['todo.exercise']['items']  | selectattr('summary','match',now().strftime('%A')) | list )  %}
          {% if (exercise_today|count) == 1 %}{{ exercise_today[0]['status'] | replace('complete','Complete') | replace('needs_action','Incomplete') }}{% else %}None{% endif %}
        attributes:
          description: >-
            {% set exercise_today = (exercise_list['todo.exercise']['items']  | selectattr('summary','match',now().strftime('%A')) | list )  %}
            {% if (exercise_today|count) == 1 %}{{ exercise_today[0]['description'] }}{% else %}None{% endif %}
          title: >-
            {% set exercise_today = (exercise_list['todo.exercise']['items']  | selectattr('summary','match',now().strftime('%A')) | list )  %}
            {% if (exercise_today|count) == 1 %}{{ exercise_today[0]['summary'] | replace(now().strftime('%A') ~ ': ','') }}{% else %}None{% endif %}
          uid: >-
            {% set exercise_today = (exercise_list['todo.exercise']['items']  | selectattr('summary','match',now().strftime('%A')) | list )  %}
            {% if (exercise_today|count) == 1 %}{{ exercise_today[0]['uid']  }}{% else %}None{% endif %}
        icon: mdi:weight-lifter