How to Use JSONata in Grafana to Validate Data

Learning how to use JSONata with Grafana delivers a huge boost to your ability to visualize data.

Golioth makes it easy to gather data from IoT sensors in the field and store them on the cloud. But of course once you have that data you probably want to graph it to show what’s going on. We like to use Grafana for this purpose. It makes beautiful interfaces and can grab Golioth data using our REST API.

Grafana fields to select JSONPath or JSONata
Grafana allows you to choose JSONPath or JSONata for each field that you use

Connecting the two is simple, but things can get hairy when trying to get Grafana to navigate the JSON structures that are returned. While JSONPath is the default setting for parsing Grafana queries, JSONata is also available and delivers some very interesting inline conditional options, and string concatenation. Let’s look at what it can do and how to use it.

Just JSONata for in-line logic

I was building a dashboard and wanted to display the current settings for a device. More specifically, I wanted to know what my “loop delay” was set to for a particular device.

I know how to call the REST API and query the settings I configured on my dashboard. However, Golioth settings can be set from the “project”, “blueprint”, or “device” level (see our introduction to the Settings Service for more information). If I filter for just one of these levels and the data isn’t present, it will cause the Grafana panel to throw an error. Our normal parsing tool (JSONPath) doesn’t provide the capabilities to differentiate between the returned data. Here’s what that data looks like:

{
  "list": [
    {
      "id": "6376a13a08be30b7e6d8669f",
      "key": "LOOP_DELAY_S",
      "value": 60,
      "dataType": "integer",
      "projectId": "636d7db608be30b7e6d865d3",
      "createdAt": "2022-11-17T21:01:46.176Z",
      "updatedAt": "2022-11-21T22:06:31.182Z"
    },
    {
      "id": "637bedbf8ad1a55c85e2894a",
      "key": "LIGHT_THRESH",
      "value": 1800,
      "dataType": "integer",
      "projectId": "636d7db608be30b7e6d865d3",
      "createdAt": "2022-11-21T21:29:35.321Z",
      "updatedAt": "2022-11-21T21:29:35.321Z"
    },
    {
      "id": "637bedcc8ad1a55c85e2894b",
      "key": "TEMP_THRESH",
      "value": 23.7,
      "dataType": "float",
      "projectId": "636d7db608be30b7e6d865d3",
      "createdAt": "2022-11-21T21:29:48.610Z",
      "updatedAt": "2022-11-21T21:29:48.610Z"
    },
    {
      "id": "637c27aa8ad1a55c85e28954",
      "key": "TEMP_THRESH",
      "value": 21.5,
      "dataType": "float",
      "projectId": "636d7db608be30b7e6d865d3",
      "deviceId": "636d7df208be30b7e6d865d6",
      "createdAt": "2022-11-22T01:36:42.195Z",
      "updatedAt": "2022-12-17T21:58:20.108Z"
    },
    {
      "id": "63978ef5e51fde6bbe11bfa6",
      "key": "LIGHT_THRESH",
      "value": 900,
      "dataType": "integer",
      "projectId": "636d7db608be30b7e6d865d3",
      "deviceId": "636d7df208be30b7e6d865d6",
      "createdAt": "2022-12-12T20:28:37.696Z",
      "updatedAt": "2022-12-12T20:28:37.696Z"
    }
  ],
  "total": 5
}

You have to look very closely at the data above to realize some entries have a deviceId field and others do not. If an entry has that key, we want to use the value to isolate just that piece of data. We also want to have a label that shows “Device” or “Project”. We can filter for this using JSONata:

list[key='LOOP_DELAY_S'][-1].deviceId ? "Device:" : list[key='LOOP_DELAY_S'].blueprintId ? "Blueprint:" : "Project:"

The code above has a few things going on:

  • First, filter all returned values for one key:
    • list[key='LOOP_DELAY_S']
  • Next, get the last value from that list:
    • [-1]
    • In our case we know the most specific settings value returned by Golioth will be the last value with that key
  • Now let’s do some inline conditional work:
    • Inline formatting works as follows: test ? use_this_if_true : use_this_if_false
    • Our example returns the string Device if it finds deviceId otherwise it tests for blueprintId and returns the string Blueprint, or finally defaults to return the string Project

The other thing we need is to write the value. But for human-readable values it’s best to return a unit as well. I used JSONata concatenation for this:

$join([$string(list[key='LOOP_DELAY_S'][-1].value), " s"])

This uses the same filtering and negative indexing tricks from above. But there are two new function calls, $string() converts the value to a string, and $join() concatenates the two strings together to add a space-S to the value.

Device settings panel in GrafanaThe panel looks great, and it’s all done with just two field settings in the Grafana:

JSONata panel settings

Just a peek at JSONata

This is just a small part of what JSONata has to offer. It has not replaced JSONpath as my go-to parsing language for Grafana, but I find it easier for filtering data, and it has inline conditionals and concatenation that I think are absent in JSONpath. Give it a spin the next time you’re stuck and see if it does the trick!

Mike Szczys
Mike Szczys
Mike is a Firmware Engineer at Golioth. His deep love of microcontrollers began in the early 2000s, growing from the desire to make more of the BEAM robotics he was building. During his 12 years at Hackaday (eight of them as Editor in Chief), he had a front-row seat for the growth of the industry, and was active in developing a number of custom electronic conference badges. When he's not reading data sheets he's busy as an orchestra musician in Madison, Wisconsin.

Post Comments

No comments yet! Start the discussion at forum.golioth.io

More from this author

Related posts

spot_img

Latest posts

Using the NXP FRDM-RW612 with Golioth

The new NXP FRDM-RW612 board comes with built-in Ethernet, and a tri-band radio. We were able to get it up and running all of the Golioth Firmware SDK sample applications in just a few hours. Here's what goes into the process.

A Sneak Peek at the Bluetooth-to-Cloud Early Access

Golioth's Bluetooth-to-Cloud is in private access currently, but this post lets you peer behind the curtain to see how it works on some development boards.

Designing and Building An AirTag Clone: A new series from Golioth

Have you ever wanted to build your own Apple AirTag? Join us for a free webinar series (starting April 11) where we walk through how to design and prototype a small, Bluetooth-enabled sensor device using Zephyr RTOS, the nRF52840, and Golioth's new Bluetooth-to-Cloud capabilities.

Want to stay up to date with the latest news?

Subscribe to our newsletter and get updates every 2 weeks. Follow the latest blogs and industry trends.