API Ninjas - parsing json data

I’m using API Ninjas to add some fun stuff to my kids morning briefings. There is one which will return a “on this day” fact. I want to generate a random number between 1900 and 2023 to feed into the API so I only get “recent” events. The API requires a string input, but for the life of me I cannot get home assistant to convert the number into a string. I’ve tried piping the result into string, using string(), etc and every time the result remains as a number. Any help on this is greatly appreciated!
Here is my current code which works. I would like to add the year param but again it needs to be a string.

- platform: rest
  name: On This Day
  unique_id: on_this_day
  resource: https://api.api-ninjas.com/v1/historicalevents?limit=1
  method: GET
  scan_interval: 7200
  headers:
    X-Api-Key: !secret ninjas_api
  params:
    month: >
      {{ (now().strftime("%m")) }}
    day: >
      {{ now().strftime("%d") }}
  value_template: "{{ value_json[0].event }}"
  json_attributes_path: "$.[0]"
  json_attributes:
    - "year"

As you have discovered, using string doesn’t influence the final result. Home Assistant employs “native typing” where the type of the template’s result is inferred from its appearance. In short, if it looks like a number, it’s a number. You cannot override this behavior with string or any other filter.

Try this version. It defines the value of params as dictionary using JSON (as opposed to defining a dictionary using YAML). This provides more control of the value type for the year, month, and day keys.

  params: {"year": "{{ range(1900, now().year)|random }}", "month": "{{ now().strftime('%m') }}", "day": "{{ now().strftime('%d')  }}"}

You can test it in the Template Editor to confirm it produces the correct values and type (string).

1 Like

Thank you for the response! Indeed this did get a string result in the template editor, but upon trying it out in “prod”, I get the following error:
JSON result was not a dictionary or list with 0th element a dictionary

New code:

- platform: rest
  name: On This Day
  unique_id: on_this_day
  resource: https://api.api-ninjas.com/v1/historicalevents?limit=1
  method: GET
  scan_interval: 7200
  headers:
    X-Api-Key: !secret ninjas_api
  params:
    {
      "year": "{{ range(1900, now().year)|random }}",
      "month": "{{ now().strftime('%m') }}",
      "day": "{{ now().strftime('%d')  }}",
    }
  value_template: "{{ value_json[0].event }}"
  json_attributes_path: "$.[0]"
  json_attributes:
    - "year"

Try it the way I posted it (all on the same line) and ensure there is no comma after the third value in the dictionary.

It was actually Home Assistant (or studio code server?) which reformatted it. I deleted that 3rd comma and now I get 2 errors:

Template variable error: list object has no element 0 when rendering ‘{{ value_json[0].event }}’

JSON result was not a dictionary or list with 0th element a dictionary

Actually when I go back to look, even if I delete the comma, it brings it back!

Those errors are for this line in the REST sensor’s configuration:

value_template: "{{ value_json[0].event }}"

It’s reporting that there’s no zeroth element in the value_json variable.

To help you, I would need to see an example of the data retrieved from api.api-ninjas.com.

I really appreciate your help. How would I get the raw json data retrieved from the api site? I don’t see it in the full logs.

If it helps, I tried simply putting
year: “1925”
and I get the same errors. But if I comment out year (keeping the month and day), it works fine but obviously returns a random year, no errors.

Hoping to revive the help on this one. I don’t know how to see what raw json is coming into home assistant in order to figure out the templating to parse out the line item I want. The API Ninjas page does show an example, but what I’m putting into the code is simply not working on home assistant. Thanks!

I don’t think this will help. YAML and JSON are interchangeable, and the template parser will still parse the individual templates to native types.

I don’t know if the params: field accepts templates, but if that is the case, this could work

params: >
  {{
    {
      "year": range(1900, now().year)|random,
      "month": now().strftime('%m'),
      "day": now().strftime('%d')
    }
  }}

@Cowboy-Ry if you enable debug logging for the rest integration, you will see the output in the logs.

1 Like