Getting familiar with npm package jsonpath

·

4 min read

JSONPath is a query language for JSON, similar to XPath for XML. It allows you to select and extract data from a JSON document. You use a JSONPath expression to traverse the path to an element in the JSON structure.

We deal with json objects in a lot of scenarios, if you are troubleshooting or are particularly looking for something specific using jsonpath could offer you a lot of help to transverse through. Be it API call responses, file templates which is in json, metadata files stored in json. Kubernetes also supports jsonpath template which can useful if you make use of its full potential. Just for an example, this below query will find out the start time of your pod:

kubectl get pods -o=jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.startTime}{"\n"}{end}'

Now, let's try to leverage the npm jsonpath package to do a few things for us for different examples:

To start to use the jsonpath npm package

npm i jsonpath

Example 1: Find type of data from json response

In the below code, response holds the json object that has data in list form, and at it's first index we have another json object which contains information about type, id, attributes and so on. Now, to write a query to find the type of data, we would write '$..data[0].type' to find the expected value as show below.

var response = {
    "data": [{
      "type": "articles",
      "id": "1",
      "attributes": {
        "title": "JSON:API paints my bikeshed!",
        "body": "The shortest article. Ever.",
        "created": "2015-05-22T14:56:29.000Z",
        "updated": "2015-05-22T14:56:28.000Z"
      },
      "relationships": {
        "author": {
          "data": {"id": "42", "type": "people"}
        }
      }
    }],
    "included": [
      {
        "type": "people",
        "id": "42",
        "attributes": {
          "name": "John",
          "age": 80,
          "gender": "male"
        }
      }
    ]
  }

var jp = require('jsonpath');
var query_result = jp.query(response, '$..data[0].type');
console.log(query_result)
Output:  [ 'articles' ]

Example 2: Finding Data Attributes

Now that the data also has attributes of article, to find the attributes at index 0 of data, we write '$..data[0].attributes'.

var jp = require('jsonpath');
var query_result = jp.query(response, '$..data[0].attributes');
console.log(query_result)
Output:  [
  {
    title: 'JSON:API paints my bikeshed!',
    body: 'The shortest article. Ever.',
    created: '2015-05-22T14:56:29.000Z',
    updated: '2015-05-22T14:56:28.000Z'
  }
]

Example 3: Included attributes with name of the people type

To find the includes fields, and name of the attributes with in it, we write '$..included[0].attributes.name'.

var jp = require('jsonpath');
var query_result = jp.query(response, '$..included[0].attributes.name');
console.log(query_result)
Output:  [ 'John' ]

All of the above three examples were of sample json object response. To try and understand let's look at another example closely.

Example 4: Finding response status

When you are dealing with nested API responses, and you would like to use jsonpath to determine the status, you'd write something similar to as shown below:

var response = {
    "responseStatus": "fail",
    "responseHeader": {
      "now": 1465840430014,
      "status": "fail",
      "requestId": null
    },
    "responseData": {
      "validationErrors": [
        {
          "category": "Vault Existence",
          "rule": "Only service or management vaults may exist",
          "objects": []
        },
        {
          "category": "API",
          "rule": "access pool(s) must change its API type to 'Cloud Storage Object'",
          "objects": [
            {
              "type": "accessPool",
              "id": 8,
              "name": "Access Pool 3"
            }
          ]
        },
        {
          "category": "Mirror",
          "rule": "Container Mode not supported on dsNets with mirrors",
          "objects": []
        }
      ],
      "migrationErrors": []
    }
  } 

var jp = require('jsonpath');
var query_result = jp.query(response, '$..responseStatus');
console.log(query_result)
Output: [ 'fail' ]

Example 5: Categories of Validation Errors

For the given list of validation errors, to find the categories of errors, we'll write something like '$..responseData.validationErrors[].category' where is the wildcard.

var jp = require('jsonpath');
var query_result = jp.query(response, '$..responseData.validationErrors[*].category');
console.log(query_result)
Output: [ 'Vault Existence', 'API', 'Mirror' ]

Example 6: Using Filters or Selectively querying based on the field name and get field value.

In this below case, we'll try to get the color code of magenta.

var colors = [
    {
        color: "red",
        value: "#f00"
    },
    {
        color: "green",
        value: "#0f0"
    },
    {
        color: "blue",
        value: "#00f"
    },
    {
        color: "cyan",
        value: "#0ff"
    },
    {
        color: "magenta",
        value: "#f0f"
    },
    {
        color: "yellow",
        value: "#ff0"
    },
    {
        color: "black",
        value: "#000"
    }
]

var jp = require('jsonpath');
var query_result = jp.query(colors, '$..[?(@.color=="magenta")].value');
console.log(query_result)
Output: [ '#f0f' ]

What [?(@.color== ] does is to identify the index at which color=='mentioned value' exist, and .value gives the value of that color in this case.

Hope these above examples were easy to understand. Comment in scenarios where you could likely use jsonpath or the different occasions in which you have already used them.

There's a really nice JsonPath tutorial and quiz to practice on KodeKloud, you should give it a try to understand jsonpath in more detail. Bonus: JSONPath cheatsheet from Kubernetes Documentation.