Add object to json in Template

Hi Guys,

I´ve been trying to get more into templating and I am currently testing arround whats possible and it went OK so far but now I got stuck.

I try to build a template for an gtfs sensor containing the next departures from the trainstation as an attribute. I want to make some kind of schedule as json file/string/object containing all these next departures in order to access them.
grafik

I managed to create some kind of json :slight_smile: but that is only for the first of a few departures “departure_1” and I cant find a way to add a second object “departure_2” to that json. Is there any easy way I am missing to achieve that?

## read sensor attribute and save it as a list
{% set next_departures_list = state_attr('sensor.mex18_es_bh','next_departures_lines') | list %}

## Load first Departure from list
{% set next_departure = next_departures_list[0] %}

## departure time of next departure
{% set next_line_deptime = next_departure[:25] %}

## calc timediff to now and testing conversion of timezone but thats not working. 
## with that code I just replace the timezone but the departure time stays the same 
{% set next_line_timediff = as_datetime(next_departure[:25]) - now() %}
How to get a string out of datetime object in order to save it in json format?

## to JSON
{% set schedule_json = {
        "next_departures": [{
            "departure_1": {
              "line": next_departure[26:].replace('(','').replace(')',''),
              "from_station_id": state_attr('sensor.mex18_es_bh','origin_station_stop_id'),
              "from_station_name": state_attr('sensor.mex18_es_bh','destination_station_stop_name'),
              'to_statio_id': state_attr('sensor.mex18_es_bh','destination_station_stop_id'),
              'to_station_name': state_attr('sensor.mex18_es_bh','origin_station_stop_name'),
              'departure_time': next_departure[:25],
              'departure_day': state_attr('sensor.mex18_es_bh','day'),
              'time_to_departure': "next_line_timediff"
              }
          }]
        }
%}

which gives me this result…
grafik

Additionally I wasn`t able to find a solution for saving datetime object within json. When I try to save the next_line_timediff as datetime I get an error message

grafik
How to convert the datetime object in oirder to save it to json?

And why cant I access the line within the first departure directly? It doesn`t even print an error message…

{{ schedule_json['next_departures'][0].line

Hope you can give me an hint into the right direction :). Thanks!

Right well the first thing I can answer is because - that doesn’t exist.
You have created an object inside index 0 called “departure_1” so it would be

schedule_json['next_departures'][0]['departure_1']['line']

So the very first thing I would suggest would be not label them as departure_1, departure_2 etc, because you are going to be adding them to an array / list inside the next_departures object anyway, just called it departure.

We need to see the output of {{ next_departure[:25] }} because we have no idea what that is outputting right now from the code you have posted.

1 Like

I suggest you change the data structure you have chosen for the value of next_departures.

Currently, each departure has a unique key in a dictionary (departure_1, departure_2, etc). I suggest you simply create a list of departures. A list structure will not make it harder to reference each departure but it will make it easier to generate multiple departures (using a for-loop to iterate through next_departures_lines).

1 Like

HI,

thank you for your answers. I tried a bit with lists before I decided to try json but your suggestion made me think of it again and I found a solution.

The key was to adding all the Information for one departure (Line, Time, Station, ID`s etc) as one List item to a list. Just tried it quick and dirty as a proof without all Information and without a loop but thats working code for me. Will post the whole solution after I am done. Thank you for pointing me to the right direction.

{{ next_departure[:25] }}

gives back the day and time of the departure with UTC timezone 2024-01-23T03:57:00+00:00.
From this point I try to calculate the time difference between now and the departure
. Therefore I need this Information as a date_time object and the result is also a date_time object. But the object can`t get serialized to an JSON.

{% set next_line_timediff = as_datetime(next_departure[:25]) - now() %}
{{ next_line_timediff }}

Saving to a list
{% set data.departures = data.departures + [{"line": "Line1", 'departure_time': next_departure[:25], 'time_to_departure': next_line_timediff}] %}

I Tried to save the timediff within a List and not in an JSON and now I can save it directly within the list but the output isn`t really what I wanted. Is will be saved within the list as datetime.timedelta. A simple string would bo ok for me.

If you look around the forum you will find datetime jinja macros - hold on -

This is what you will be wanting to convert your next_line_timediff to I assume you are wanting 13mins etc

1 Like

Thats exactly what I want. Great thank you!

1 Like

Hi,

with your help I found a solution, thank you!

{% from 'easy_time.jinja' import easy_time_between %}
## Set variables
{% set data = namespace(departures=[]) %}
{% set origin_station_name = state_attr('sensor.mex12_bh_es','origin_station_stop_name')%}
{% set destination_station_name = state_attr('sensor.mex12_bh_es','destination_station_stop_name')%}
## Loop through departure_list
{% for departure in state_attr('sensor.mex12_bh_es','next_departures_lines') | list %}
  {% set departure_line = departure[27:].replace('(','').replace(')','') %}
  {% set departure_time = departure[:25] %}
  {% set departure_timediff = easy_time_between(now(), departure_time) %}
  {% set data.departures = data.departures + [{"line": departure_line, "origin_station_name": origin_station_name, "destination_station_name": destination_station_name, "time": departure_time, "timediff": departure_timediff }]%}
{% endfor %}
## Output
{{ data.departures | to_json(pretty_print=true)}}

## output departure 1
{{ data.departures[0].line }} {{ data.departures[0].time }}

## output departure 2
Line: {{ data.departures[1].line }}
Departure Time: {{ data.departures[1].time[11:19] }}
Time to Departure: {{ data.departures[1].timediff }}

This Template gives me the output I wanted.

Next steps is to add a second gtfs sensor with departures from the same Station, combine the departures from these Sensors and sort them in the order of the departure time. But thats an other topic :). Thank You again!