JSON k,v storage, retrieval and modification

Hi all,
I spent quite a bit of time today trying to find a way to use an input_text entity to store JSON, and then later retrieve, modify and update the JSON key values. This turned out to be way more complicated than I expected due to the limitations of the Jinja2 implementation in HA.

I’m sharing my resulting script in hopes it helps someone else with this process. Note that as of now, this is only capable of handling single level JSON, not multi-level nested data.

alias: Set / Remove Key from input_text JSON
sequence:
  - action: input_text.set_value
    metadata: {}
    data:
      value: >-
        {% set b = states(text_entity) | from_json %}{% set j = namespace(b={})
        %}{%  for k in b %}{%  if k != key_name %}{%  set j.b = dict( j.b, **{
        k: b[k] }) %}{%  endif %}{%  endfor %}{% if key_value is defined %}{% 
        set j.b = dict( j.b, **{key_name: key_value} ) %}{% endif %}{{ j.b |
        to_json }}
    target:
      entity_id: "{{ text_entity }}"
fields:
  text_entity:
    selector:
      entity: {}
    name: Text Entity
    description: Entity ID of the input_text helper
    required: true
  key_name:
    selector:
      text: null
    name: Key Name
    description: Name of the key to update or remove
    required: true
  key_value:
    selector:
      text: null
    name: key_value
    description: Value to update to the key, blank to remove the key
description: ""
icon: mdi:code-json

Example usage:
Add / Update a Key

action: script.set_remove_key_from_input_text_json
data:
  text_entity: "input_text.my_json_epochs"
  key_name: "Key1"
  key_value: "{{ as_timestamp(now()) }}"

Remove a Key

action: script.set_remove_key_from_input_text_json
data:
  text_entity: "input_text.my_json_epochs"
  key_name: "Key1"

To use the JSON values in a template for automation or other scripts:

actions:
  - variables:
      b: |
        {{ states('input_text.my_json_epochs) | from_json }}
  - if:
      - condition: template
        value_template: "{{ 'Key1' in b }}"
    then:
      - data:
          message: "Key1 was set {{ (( as_timestamp(now()) - b['Key1'] ) / 60 )| round(1) }}" minutes ago
          notification_id: infonotice
          title: "My Title"
        continue_on_error: true
        action: persistent_notification.create

I’d be eager to get any feedback on how to improve or make this process more efficient!

Thanks!
LK

For one thing, all of your script/variable names seem a tad unnecessarily verbose :stuck_out_tongue:

Also seems annoying having to specify which input_text to store data in. Would it not be more convenient to just have the one global storage? Then maybe have it so you can include an optional unique ID only if it is important that you really avoid conflicts, yet insist on generic variables names. Or use the ID or entity ID of the calling automation/script.

Of course one big limitation is that the max length for an input_text seem to be only 255 characters. However I don’t see anything in the documentation regarding limits on an input_select, so perhaps using one of those would allow much larger storage space…?

1 Like

I suggest you just use @TheFes’s variable template entity. Hopefully he can link it here.

Here you go

1 Like

Thanks! I’m not sure how I didn’t come across @TheFes solution. I suspect it was because I thought it should be so easy to do with jinja2, so I kept searching for jinja2 methods of manipulation. It turned out to absolutely NOT be easy to do json manipulation in jinja2 without looping.

Now I’m off to change to this trigger template method… :slight_smile:
LK