@warren-bank/immutable-jsonpath
v3.1.1
Published
jsonpath enhancement: extends class prototype with immutable assignment of value to pathExpression
Downloads
472
Readme
immutable-jsonpath
Summary:
jsonpath enhancement: extends class prototype with immutable assignment of value to pathExpression
Installation:
npm install --save 'jsonpath'
npm install --save '@warren-bank/immutable-jsonpath'
Methods:
jsonpath.assign(obj, pathExpression, newValue)
Returns a clone of obj
having the following properties:
- every node traversed between the root (
$
) and the target path node (pathExpression
) are also cloned - the target path node (
pathExpression
) is replaced bynewValue
const jsonpath = require('jsonpath')
// apply enhancement to jsonpath class prototype
require('@warren-bank/immutable-jsonpath')(jsonpath)
const deepFreeze = require('deep-freeze')
deepFreeze(data)
const newData = jsonpath.assign(data, '$.store.bicycle.color', 'blue')
// cloned Objects
expect(newData).not.toBe(data)
expect(newData.store).not.toBe(data.store)
expect(newData.store.bicycle).not.toBe(data.store.bicycle)
expect(newData.store.bicycle.color).not.toBe(data.store.bicycle.color)
// not cloned
expect(newData.store.book).toBe(data.store.book)
jsonpath.update(obj, pathExpression, operation, ...data)
Returns a clone of obj
having the following properties:
- every node traversed between the root (
$
) and the target path node (pathExpression
) are also cloned - the clone of the target path node (
pathExpression
) is a collection data type:Array
orObject
- the clone of the target path node (
pathExpression
) has been updated by anoperation
operation
is a stringdata
contains parameters to configure the behavior of theoperation
- its length and data types are dependent upon the particular
operation
- its length and data types are dependent upon the particular
considerations:
this can be thought of as a convenience method
- to update a collection (ie: Array, Object) at
pathExpression
inobj
- a common pattern may emerge:
let old_val = jsonpath.value(obj, pathExpression) let new_val = {...old_val} // mutate new_val // assign new_val to `pathExpression` in `obj` resulting in a clone of the Object let new_obj = jsonpath.assign(obj, pathExpression, new_val)
- this can become tedious
- the way
new_val
is mutated in the vast majority of cases is fairly predictable - much of this boilerplate can be performed by a helper function
- a common pattern may emerge:
- to update a collection (ie: Array, Object) at
my first inclination was to borrow the API convention used by immutability-helper
- instead, I decided to simplify the API and only focus on the primary use cases
- anything more complicated can follow the above pattern and take complete control of the update operation
- instead, I decided to simplify the API and only focus on the primary use cases
operations:
to perform on an
Array
:delete
- removes 1+ elements from Array beginning at a start index
data
:- <integer>start
- index of first element to delete
- a negative value is subtracted from the length of the Array
- [<integer>deleteCount]
- count of elements to delete at
start
- default = 1
- count of elements to delete at
- <integer>start
- notes:
data
can be passed to the function as either:- a single Array value
- individual arguments
- example:
const data = {path: {to: {arr: ["a","b","c"]}}} const clone = jsonpath.update(data, '$.path.to.arr', 'delete', 1) expect(clone.path.to.arr).toEqual(["a","c"])
shift
- removes the first element from Array
- note:
- the element is discarded
- example:
const data = {path: {to: {arr: ["a","b","c"]}}} const clone = jsonpath.update(data, '$.path.to.arr', 'shift') expect(clone.path.to.arr).toEqual(["b","c"])
pop
- removes the last element from Array
- note:
- the element is discarded
- example:
const data = {path: {to: {arr: ["a","b","c"]}}} const clone = jsonpath.update(data, '$.path.to.arr', 'pop') expect(clone.path.to.arr).toEqual(["a","b"])
unshift
- inserts 1 element to the beginning of the Array
data
:- <Any>value
- example:
const data = {path: {to: {arr: ["a","b","c"]}}} const clone = jsonpath.update(data, '$.path.to.arr', 'unshift', '0') expect(clone.path.to.arr).toEqual(["0","a","b","c"])
push
- inserts 1 element to the end of the Array
data
:- <Any>value
- example:
const data = {path: {to: {arr: ["a","b","c"]}}} const clone = jsonpath.update(data, '$.path.to.arr', 'push', '4') expect(clone.path.to.arr).toEqual(["a","b","c","4"])
concat_start
- concatenates the elements of an input Array to the beginning of the Array
data
:- <Array>value
- example:
const data = {path: {to: {arr: ["a","b","c"]}}} const clone = jsonpath.update(data, '$.path.to.arr', 'concat_start', ["0","1","2"]) expect(clone.path.to.arr).toEqual(["0","1","2","a","b","c"])
concat_end
- concatenates the elements of an input Array to the end of the Array
data
:- <Array>value
- example:
const data = {path: {to: {arr: ["a","b","c"]}}} const clone = jsonpath.update(data, '$.path.to.arr', 'concat_end', ["4","5","6"]) expect(clone.path.to.arr).toEqual(["a","b","c","4","5","6"])
slice
- replaces the Array with a contiguous subset of its elements
- same input parameters as Array.slice
data
:- <integer>start
- index of first element to extract into subset
- a negative value is subtracted from the length of the Array
- [<integer>end]
- index of first element (following
start
) to exclude from contiguous subset - a negative value is subtracted from the length of the Array
- default = length of the Array
- index of first element (following
- <integer>start
- notes:
data
can be passed to the function as either:- a single Array value
- individual arguments
- example:
const data = {path: {to: {arr: ["a","b","c"]}}} const clone = jsonpath.update(data, '$.path.to.arr', 'slice', 0, 2) expect(clone.path.to.arr).toEqual(["a","b"])
splice
- changes the contents of the Array by removing existing elements and/or adding new elements
- same input parameters as Array.splice
data
:- <integer>start
- index of element at which to start changing the Array
- a negative value is subtracted from the length of the Array
- [<integer>deleteCount]
- count of elements to delete, beginning at
start
- default = all elements following
start
- count of elements to delete, beginning at
- [<Any>item1, <Any>item2, ...]
- elements to add to the Array, beginning at
start
- elements to add to the Array, beginning at
- <integer>start
- notes:
data
can be passed to the function as either:- a single Array value
- individual arguments
- example:
const data = {path: {to: {arr: ["a","b","c"]}}} const clone = jsonpath.update(data, '$.path.to.arr', 'splice', 2, 1, "3") expect(clone.path.to.arr).toEqual(["a","b","3"])
filter
- replaces the Array with a filtered subset of elements
- similar behavior to Array.filter
data
:- <Function>callback
- parameters passed to
callback
:element
- current element being processed
index
- index of the current element being processed
- return value from
callback
:- boolean
true
indicates thatelement
is included in resulting subset
- boolean
- parameters passed to
- <Function>callback
- example:
const data = {path: {to: {arr: ["a","b","c"]}}} const fn = element => element === 'b' const clone = jsonpath.update(data, '$.path.to.arr', 'filter', fn) expect(clone.path.to.arr).toEqual(["b"])
map
- replaces the Array with a new Array
- same length as original Array
- elements are mapped by a
callback
function
- similar behavior to Array.map
data
:- <Function>callback
- parameters passed to
callback
:element
- current element being processed
index
- index of the current element being processed
- return value from
callback
:- mapped value of
element
- mapped value of
- parameters passed to
- <Function>callback
- example:
const data = {path: {to: {arr: ["a","b","c"]}}} const fn = element => `(${element})` const clone = jsonpath.update(data, '$.path.to.arr', 'map', fn) expect(clone.path.to.arr).toEqual(["(a)","(b)","(c)"])
- replaces the Array with a new Array
to perform on an
Object
:delete
- removes a single attribute
data
:- <string>key
- attribute key to remove from the Object
- <string>key
- example:
const data = {path: {to: {obj: {a:"a", b:"b", c:"c"}}}} const clone = jsonpath.update(data, '$.path.to.obj', 'delete', 'b') expect(clone.path.to.obj).toEqual({a:"a", c:"c"})
add
- merges data from an input Object into the Object
data
:- <Object>value
- example:
const data = {path: {to: {obj: {a:"a", b:"b", c:"c"}}}} const clone = jsonpath.update(data, '$.path.to.obj', 'add', {d:"d", e:"e"}) expect(clone.path.to.obj).toEqual({a:"a", b:"b", c:"c", d:"d", e:"e"})
subtract
- removes 1+ attributes
data
:- <Object | Array>value
- collection of attribute keys to remove from the Object
- <Object | Array>value
- example:
const data = {path: {to: {obj: {a:"a", b:"b", c:"c"}}}} const clone = jsonpath.update(data, '$.path.to.obj', 'subtract', ["a","c"]) expect(clone.path.to.obj).toEqual({b:"b"})
More Examples:
in node.js:
in the web browser:
Browser Build (transpiled to ES5):
files in repo:
files hosted in CDN:
global variable(s):
- N/A
- the enhancement is applied to jsonpath automatically
- make certain that jsonpath is loaded before the enhancement script
- N/A
Legal:
- copyright: Warren Bank
- license: GPL-2.0