Why do input_* need 'data'?

It’s only a small irritation but why can’t input_* services be writtten

For example:

- service: input_text.set_value
  entity_id: input_text.my_input_text
  value: Some text here

Instead of

- service: input_text.set_value
  entity_id: input_text.my_input_text
  data:
    value: Some text here

Obviously using data_template where necessary

- service: input_text.set_value
  data_template:
    entity_id: input_text.my_input_text
    value: "{{ some template here }}"

All extra attributes go inside data, even entity_id. entity_id is also the only exception to the rule (it can go inside or outside). If this change were to go through, this would be the only service that doesn’t use data/data_template.

Why does it require data? Because under the hood, the call.service function requires the domain, the service string, and a dictionary containing information for the service. The domain and service string are pulled from the service by splitting on the .. The dictionary containing information is data. Nothing needs to be modified, it’s a straight shot into the call.

If we were to change this, all service calls would need to be tailored for this change as well. It could be done, but is the juice worth the squeeze? Not really. It’d be a massive amount of busy work changing all the validation in every integration. Then after all that’s done, you’d have to change actions inside the script editor & automation editor because the data is served up differently. Then lovelace’s tap action call-service would need to be changed to allow values outside service_data… I’m sure there’s other things too that aren’t coming to the top of my head.

In some instances placement of entity id is actually really specific and inconsistent:

Yep, that’s why you’ll notice most of my support posts always have this format (because it works 100% of the time):

service: x.y
data:
  entity_id: a.b

Except for this one instance: