A TypeScript/JavaScript library that provides a simple way of accessing objects inside JSON using paths
npm install @jsonhero/path
You can require
const { JSONHeroPath } = require('@jsonhero/path');
Or if you're using TypeScript:
import { JSONHeroPath } from '@jsonhero/path';
Given the following JSON variable called employees
let employees = { people: [ { name: 'Matt', age: 36, favouriteThings: ['Monzo', 'The Wirecutter', 'Jurassic Park'], }, { name: 'James', age: 39, favouriteThings: ['Far Cry 1', 'Far Cry 2', 'Far Cry 3'], }, { name: 'Eric', age: 38, favouriteThings: ['Bitcoin'], }, { name: 'Dan', age: 34, favouriteThings: ['Frasier'], }, ], count: 4, };
A simple query to get the 2nd person's name. Note that you can just include index numbers to access array items (0 = first item)
let path = new JSONHeroPath('$.people.1.name'); let name = path.first(employees); //name = 'James' let names = path.all(employees); //names = ['James']
Let's get all the people
let path = new JSONHeroPath('$.people'); let allPeople = path.all(employees); //allPeople is set to the array of people
There are only two methods you can perform with a path:
first()returns the first matching resultall()returns all the matching results in an array
A $ is placed at the start of a path. If you don't add this, it will just do it automatically for you.
Let's get all the names
let path = new JSONHeroPath('$.people.*.name'); let allNames = path.all(employees); //allNames = ['Matt', 'James', 'Eric', 'Dan']
Now everyone's favourite things
let path = new JSONHeroPath('$.people.*.favouriteThings.*'); let allFavouriteThings = path.all(employees); //allFavouriteThings = ['Monzo', 'The Wirecutter', 'Jurassic Park', 'Far Cry 1', 'Far Cry 2', 'Far Cry 3', 'Bitcoin', 'Frasier']
We can slice arrays (in the exact same way as the JavaScript .slice() function).
Offset the start index
let path = new JSONHeroPath('$.people.[1:]'); let skipFirstPerson = path.all(employees); // skipFirstPerson will have everyone but the first person in
Restrict the end index
let path = new JSONHeroPath('$.people.[1:2]'); let justTheSecondPerson = path.all(employees); // justTheSecondPerson will have only the second person in (start index is 1 and the end won't include index 2)
Negative end indexes remove items from the end of an array
let path = new JSONHeroPath('$.people.[:-1]'); let excludeLastPerson = path.all(employees); // excludeLastPerson will have everyone except the last person
let path = new JSONHeroPath('$.people.*.favouriteThings.*'); // pass this optional object with `includePath` set to true let results = path.all(testObject1, { includePath: true }); let firstResult = results[0]; //this variable will be an object like this //{ // value: 'Monzo', // path: a JSONHeroPath for this element //}
let path = new JSONHeroPath('$.people.*.favouriteThings'); let parent = path.parent; // will be a new path: '$.people.*' let root = path.root; // will be a new path: '$' let child = path.child('2'); //will be a new path: '$.people.*.favouriteThings.2'
A path is an array of path components. You can access them directly if you'd like.
You can check if a component is an array type, which is true for wildcards and indexes (e.g. 0)
let path = new JSONHeroPath('$.people.2.favouriteThings.*'); let rootComponent = path.components[0]; let rootComponentIsArray = rootComponent.isArray; //is false let personIndexComponent = path.components[2]; let personIndexComponentIsArray = personIndexComponent.isArray; //is true let wildcardComponent = path.components[4]; let wildcardComponentIsArray = wildcardComponent.isArray; //is true
You can update values in an object at the specified path.
Overwriting a single object at a path:
let path = new JSONHeroPath('$.people.1'); //this will overwrite the entire object at that path path.set(employees, { name: 'James', age: 100, favouriteThings: ['Far Cry 1', 'Far Cry 2', 'Far Cry 3', 'Far Cry 4', 'Far Cry 5', 'Far Cry 6'], });
This will overwrite all the objects at the path:
let path = new JSONHeroPath('$.people.*.favouriteThings'); //this will set everyone's favourite things to be an array with just Jurassic Park in it path.set(employees, ['Jurassic Park']);
You can merge values into arrays and objects.
For an array this will append the passed in values to the end of the array
let path = new JSONHeroPath('$.people.*.favouriteThings'); //this will add Groundhog Day and Milkshakes to everyone's favourite things path.merge(employees, ['Groundhog Day', 'Milkshakes']);
For an object, this will overwrite properties that already exist and add any that don't
let path = new JSONHeroPath('$.people.*'); //this will update everyone's age to be 21 and add a new hairColour property with a value of Brown path.merge(employees, { age: 21, hairColour: 'Brown', });