How to get data with multiple values from a REST api where JSON root is an array?

The API response contains an array like:

[
  {
    "name": "example",
    "status": "active"
  },
  {
    "name": "example2",
    "status": "inactive"
  },
  {
    "name": "example3",
    "status": "active"
  }
]

I want to display these values in a table on a dashboard. I took the markdown table route. to put the values in attribute of a sensor and then loop through them in dashboard.

rest_command:
  get_values:
    url: "https://example/api/times/1"
    method: GET

template:
  - triggers:
      - platform: time_pattern
        minutes: "/1"
    actions:
      - action: rest_command.get_values
        response_variable: data
    sensor:
      - name: "My Schedule"
        unique_id: my_schedule_1
        state: "{{ data.content | from_json | length if data.content is defined else 0 }}"
        attributes:
          values: "{{ data.content | from_json if data.content is defined else [] }}"
          last_updated: "{{ now() }}" 

However this does not add the attribute for some reason. Is there any way to do this where the root element of json is an array.

Is the state populated with the length as expected? Is it only the values attribute that isn’t populated? If you just make the state say 0 and put only data in that attribute, what do you get?

Alternatively, try one of the REST sensor platforms, which I think is a bit better suited for this, but I don’t see an immediate issue with your config, unless the is defined check isn’t working as expected.

1 Like

As Pieter says, make the state empty or Hello world. Your example is 184 characters. I suppose your real data is more and probably past the 255 limit.

I could have sworn that state was defined and had the correct value as I had seen it in the past which equalled length of the array. And It was the values attribute that did not exist. However now I am getting error in the logs

ERROR (MainThread) [homeassistant.helpers.script.trigger_update_coordinator] Trigger Update Coordinator: Error executing script. Service not found for call_service at pos 1: Action rest_command.get_values not found

So I switched to using REST sensor. I had switched to REST command because in the past I was creating more sensors i.e. retrieve first 3 values in the array and put each one in their own sensor. That was not scalable as I wanted more values and the API does not always return 3 values. It can be more or less. Now I am trying REST sensor.

  - platform: rest
    resource: "https://example/api/times/1"
    name: test
    value_template: "OK"
    json_attributes:
      - data
    json_attributes_path: "$"

I do see the value ā€œOKā€ but not attributes. Because the root of JSON is just an array. How do I refer to it using json_attributes_path and then put it in json_attributes. I thought it was not possible.

The data key isn’t in your response: you created it in the rest_command, but it makes no sense in your sensor config.

An array response isn’t great to deal with. See my solution to a prior similar problem here:

Remember besides this one, there’s also this one for multiple sensors.

But as Troon pointed out, this is tricky to deal with regardless of the platform used. Unfortunately, many APIs do this kind of thing.

Your problem is that you used the name values for your attribute. values has a very specific meaning for a dictionary (which is what attributes are). Change the attribute to anything other than values, items, or keys.

I already have it working with that kind of solution where i use array indices like [0], [1] and so on. But I want to move to more dynamic solution which regardless of number of items in array it shows a table on a dashboard.

yeah those didn’t help either. I wish the json attribute parsing logic had something simpler like ā€œ$ā€ that refers to full json instead of having to have a key at the root level.

Yes, because the problem is that you’re using values as your attribute name. Use any other attribute name and it will work.

I.e.

rest_command:
  get_values:
    url: "https://example/api/times/1"
    method: GET

template:
  - triggers:
      - platform: time_pattern
        minutes: "/1"
    actions:
      - action: rest_command.get_values
        response_variable: data
    sensor:
      - name: "My Schedule"
        unique_id: my_schedule_1
        state: "{{ data.content | from_json | length if data.content is defined else 0 }}"
        attributes:
          content: "{{ data.content | from_json if data.content is defined else [] }}"
          last_updated: "{{ now() }}" 

Nothing that I did not read all responses…just ideas on orig post
Another way is to use command_line

command_line:
  - sensor:
        name: something
		command: >
			 echo "{\"whatever\":" $(
			 curl 
			 -s 
			 'https://example/api/times/1'
			 ) "}" 
		value_template: > 
			{{ value_json.whatever | length }}
		json_attributes:
			- whatever 

it may need an additional -X GET for the curl

Another one which visually looks better is to pipe the output of the curl through jq with a short statement to have an output ā€˜whatever’

command_line:
  - sensor:
        name: something
        command: >
            curl -X GET 'https://example/api/times/1' | jq '{"whatever": .[]'
        value_template: "{{ now() }}"
        json_attributes:
            - whatever