Working with JSON in JS, the easy way! JSONata
Tags: javascript, webdev, programming, development
Published: 2021-02-10 21:02:06

Data structures are one of the most important elements in any programming language. It allows us to structure the data in a consistent way and to perform operations that require some patterns. Without a pattern it is hard for any developer to figure out an efficient way to extract or manipulate the data.

As an example, `JSON` is a very well known format that most of us uses every day.
When working with it, there are operations we do regularly, such as querying, filtering, sorting, grouping and others. 

Recently, while working on a project, I needed two things, proper functions for all of these operations, and some sort of expressions for external users. I quickly realised that this wasn’t a small task.

We, as Software Developers, always get excited with these tasks, we can get creative and explore a lot, but we should not try to reinvent the wheel. I recently read a great book called _Getting real_, it really helped me focus on my goals and, in this particular case, quickly realise that before trying to implement this I should look for existent solutions.

And that’s when I came across **JSONata**, a really powerful library that did everything what I was looking for and more! 

In this article I would like to give you a quick introduction to JSONata and show how easy it is to work with JSON.

&nbsp;
## Usage
&nbsp;

```javascript
const jsonata = require('jsonata');

const data = [
  {
     field: 'some-field',
     createdAt: '2021-01-03T21:58:31.000Z'
  }
];

const expression = jsonata('$[createdAt="2021-01-03T21:58:31.000Z"]');
const result = expression.evaluate(data);
```
&nbsp;
## Expressions for your day to day needs
&nbsp;

JSONata helps us solve the most common cases when it comes to extracting data from JSON. In this article I cover some basic expressions that will help you get started with the library.

We will use the following JSON to test our expressions.

```javascript
[
  {
    "uniqueId": "9157c740159e4ff18b4a42d4a0c39622",
    "data": {
      "name": "Eduardo",
      "phone": 999888727,
      "age": 30
    },
    "createdAt": "2021-02-03T21:54:37.000Z",
    "updatedAt": "2021-02-03T21:54:37.000Z"
  },
  {
    "uniqueId": "66a1212c55ce47f9bc055e6c331b7af3",
    "data": {
      "name": "Miguel",
      "age": 17,
      "phone": 999888777
    },
    "createdAt": "2021-02-03T21:56:54.000Z",
    "updatedAt": "2021-02-03T21:56:54.000Z"
  },
  {
    "uniqueId": "86011b52ebc640aeba53a6e09a9d9773",
    "data": {
      "name": "Marco",
      "age": 18
    },
    "createdAt": "2021-02-04T21:57:59.000Z",
    "updatedAt": "2021-02-04T21:57:59.000Z"
  },
  {
    "uniqueId": "0f6586aa7ccf4901a3f066eeeea69116",
    "data": {
      "name": "Sergio",
      "age": 28,
      "jobDetails": {
        "company": "SpaceY"
      }
    },
    "createdAt": "2021-02-07T22:02:50.000Z",
    "updatedAt": "2021-02-07T22:02:50.000Z"
  }
]
```

You can try out these expressions at [https://try.jsonata.org](https://try.jsonata.org).

&nbsp;
## Simple queries
&nbsp;

#### data.name

Gets an array of names.

#### Result
```json
[
  "Eduardo",
  "Miguel",
  "Marco",
  "Sergio"
]
```

---

#### $[1]

Gets the second element.

#### Result
```json
{
  "uniqueId": "66a1212c55ce47f9bc055e6c331b7af3",
  "data": {
    "name": "Miguel",
    "age": 17,
    "phone": 999888777
  },
  "createdAt": "2021-02-03T21:56:54.000Z",
  "updatedAt": "2021-02-03T21:56:54.000Z"
}
```

---

#### $[0]data.name

Gets the name of the first element.

#### Result
```json
"Eduardo"
```

&nbsp;
## Filtering
&nbsp;

#### $[data.name="Eduardo"]

Filters records in the array containing the path _data.name_ and matching _Eduardo_.

#### Result
```json
{
  "uniqueId": "9157c740159e4ff18b4a42d4a0c39622",
  "data": {
    "name": "Eduardo",
    "phone": 999888727,
    "age": 30
  },
  "createdAt": "2021-02-03T21:54:37.000Z",
  "updatedAt": "2021-02-03T21:54:37.000Z"
}
```

---

#### $[data.jobDetails]

Filters records in the array containing the path _data.jobDetails_.

#### Result
```json
{
  "uniqueId": "0f6586aa7ccf4901a3f066eeeea69116",
  "data": {
    "name": "Sergio",
    "age": 28,
    "jobDetails": {
      "company": "SpaceY"
    }
  },
  "createdAt": "2021-02-07T22:02:50.000Z",
  "updatedAt": "2021-02-07T22:02:50.000Z"
}
```

---

#### $[data.age > 16 and data.age < 20]

Filters records in the array with _data.age_ between 16 and 20.

#### Result
```json
[
  {
    "uniqueId": "66a1212c55ce47f9bc055e6c331b7af3",
    "data": {
      "name": "Miguel",
      "age": 17,
      "phone": 999888777
    },
    "createdAt": "2021-02-03T21:56:54.000Z",
    "updatedAt": "2021-02-03T21:56:54.000Z"
  },
  {
    "uniqueId": "86011b52ebc640aeba53a6e09a9d9773",
    "data": {
      "name": "Marco",
      "age": 18
    },
    "createdAt": "2021-02-04T21:57:59.000Z",
    "updatedAt": "2021-02-04T21:57:59.000Z"
  }
]
```
&nbsp;
## Pagination
&nbsp;

#### $[[0..1]]

Gets the first 2 elements.

#### Result
```json
[
  {
    "uniqueId": "9157c740159e4ff18b4a42d4a0c39622",
    "data": {
      "name": "Eduardo",
      "phone": 999888727,
      "age": 30
    },
    "createdAt": "2021-02-03T21:54:37.000Z",
    "updatedAt": "2021-02-03T21:54:37.000Z"
  },
  {
    "uniqueId": "66a1212c55ce47f9bc055e6c331b7af3",
    "data": {
      "name": "Miguel",
      "age": 17,
      "phone": 999888777
    },
    "createdAt": "2021-02-03T21:56:54.000Z",
    "updatedAt": "2021-02-03T21:56:54.000Z"
  }
]
```
---

#### $[[2..4]]

Gets the second 2 elements.

#### Result
```json
[
  {
    "uniqueId": "86011b52ebc640aeba53a6e09a9d9773",
    "data": {
      "name": "Marco",
      "age": 18
    },
    "createdAt": "2021-02-04T21:57:59.000Z",
    "updatedAt": "2021-02-04T21:57:59.000Z"
  },
  {
    "uniqueId": "0f6586aa7ccf4901a3f066eeeea69116",
    "data": {
      "name": "Sergio",
      "age": 28,
      "jobDetails": {
        "company": "SpaceY"
      }
    },
    "createdAt": "2021-02-07T22:02:50.000Z",
    "updatedAt": "2021-02-07T22:02:50.000Z"
  }
]
```
&nbsp;
## Sorting
&nbsp;

#### $[] ~> $sort(function($a,$b){ $a.data.age > $b.data.age })

Sorts the results by ascending age. In this expression we use the **$sort** function to sort the results.

#### Result
```json
[
  {
    "uniqueId": "66a1212c55ce47f9bc055e6c331b7af3",
    "data": {
      "name": "Miguel",
      "age": 17,
      "phone": 999888777
    },
    "createdAt": "2021-02-03T21:56:54.000Z",
    "updatedAt": "2021-02-03T21:56:54.000Z"
  },
  {
    "uniqueId": "86011b52ebc640aeba53a6e09a9d9773",
    "data": {
      "name": "Marco",
      "age": 18
    },
    "createdAt": "2021-02-04T21:57:59.000Z",
    "updatedAt": "2021-02-04T21:57:59.000Z"
  },
  {
    "uniqueId": "0f6586aa7ccf4901a3f066eeeea69116",
    "data": {
      "name": "Sergio",
      "age": 28,
      "jobDetails": {
        "company": "SpaceY"
      }
    },
    "createdAt": "2021-02-07T22:02:50.000Z",
    "updatedAt": "2021-02-07T22:02:50.000Z"
  },
  {
    "uniqueId": "9157c740159e4ff18b4a42d4a0c39622",
    "data": {
      "name": "Eduardo",
      "phone": 999888727,
      "age": 30
    },
    "createdAt": "2021-02-03T21:54:37.000Z",
    "updatedAt": "2021-02-03T21:54:37.000Z"
  }
]
```
&nbsp;
## Working with dates
&nbsp;

#### Combining $filter and $toMillis

```text
$[] ~> $filter(function($value){
    $toMillis($value.createdAt)>$toMillis("2021-02-07T22:00:00.000Z")
})
```

**$toMillis** converts a _ISO 8601_ date to milliseconds. In this example we filter all the elements created after _2021-02-07 22:00:00_.

#### Result
```json
{
  "uniqueId": "0f6586aa7ccf4901a3f066eeeea69116",
  "data": {
    "name": "Sergio",
    "age": 28,
    "jobDetails": {
      "company": "SpaceY"
    }
  },
  "createdAt": "2021-02-07T22:02:50.000Z",
  "updatedAt": "2021-02-07T22:02:50.000Z"
}
```
&nbsp;
&nbsp;
And this is all for now. I hope you find this article useful, and don't forget to give JSONata a go!

PS: In case you are wondering, I’m not the author and I'm not part of the team, I just liked it so much that I thought it would be worth sharing with others! All the Kudos goes to the JSONata team!