How to write state values to file in json format?

Hi

I want to write data to a file and then use the information to configure some functions after a restart.
In this example is it the zone in which my automower “zlatan” is working.

I use a file sensor to read information from a file.

sensor:
  - platform: file
    name: ZZ zone
    file_path: logs/zlatan_zone_selected_zone.json
    value_template: '{{ value_json.zone }}'

This sensor needs the data on a json format as in the sample below.

{"zone": "front"}

The problem is to write the data to the file with correct format. I use a file notification and it is working fine as long as the value is hardcoded.

notify:
  - platform: file
    name: log_zz_state
    filename: logs/zlatan_zone_selected_zone.json
    timestamp: false

automation:
  - alias: "automation_zlatan_zone_front"
    - service: notify.log_zz_state
      data:
        message: "{\"zone\": \"front\"}"

But I should not need to hardcode the value. The zones are listed in an input_select list and I want to dynamically write the value to the file, but it will not work.

automation:
  - alias: "automation_zlatan_zone_front"
    - service: notify.log_zz_state
      data:
        message: "{\"zone\": \"{{ states('input_select.select_zlatan_zones') }}\"}"

I can write a state value to a file, but when I add the correct format with brackets, double quotation marks and colon then the notification will crash. Why?

What am I doing wrong?
//Mats

Have you tried it without the escaping/quotes.
If i try your code (with one of my input_select’s) in Dev Tools/Templates it returns a dict.


Welcome to HA, btw! :slight_smile:

It’s because of what VDRainer is showing. All Jinja templates result in a string, always. HA though has made them smarter by converting things which look like a number, boolean, dictionary or array into their actual types.

Most of the time this is extremely convenient! However this is a case where those smarts backfired. HA sees that your result looks like a dictionary and so it turns it into an actual dictionary (like in VDRainer’s screenshot). But the message input was expecting a string so now its confused why you gave it a dictionary.

My first suggestion is simple - don’t use JSON. CSV for example does not have issues like this since that’s not how python dictionaries are serialized.

If you really want to use JSON (say perhaps you intend to have nested structures down the line) then a workaround could be pretending it’s CSV anyway by writing out something like this:

service: notify.log_zz_state
data:
  message: "{\"zone\": \"front\"},"

Notice the extra comma on the end this technically makes it a two column CSV file even though we both know you only care about column one. But doing that means the actual text coming out of that template is not valid JSON so HA will leave it as a string and not turn it into a dictionary. Or another option is to put a timestamp on the front of the time you logged it like this:

service: notify.log_zz_state
data:
  message: "{{ now() }}: {\"zone\": \"front\"}"

Of course this may make dealing with this file a bit more challenging since its not a pure JSON log anymore. If it really absolutely must be a valid JSON object in every row then you can do that. To do that don’t use file notifier at all, instead use command line notify like this:

notify:
- platform: command_line
  name: Log ZZ State
  command: "sed 's/^!//' >> logs/zlatan_zone_selected_zone.json"

And then when actually logging to that file do this:

service: notify.log_zz_state
data:
  message: "!{\"zone\": \"front\"}"

It’s basically the same trick, throw in an extra character to make it not valid JSON so HA doesn’t make it into a dictionary. Except in this case sed strips it back off before logging it so we are just adding a JSON object to the end of the file.

1 Like

Thanks for this explanation! :+1:

Hi and thanks for the responce. :slight_smile:
An extra character makes the notification to work, but as soon as I leave the strict json format then the file sensor can’t recognize the information.
I will test the command_line notification later today. Thanks.

The command line notification is working perfect. Thanks for that solution. :smiley:

I hope i have found the right topic.

The value of this state:

{{states(‘sensor.envoy_122248025029_current_power_production’)}}

should go to a json like this:

{
    "pv": {
        "power": 3330.0,
        "L1": {
            "power": 3300.0
        }
    }
}