Traverse and manipulate JSON objects.
Usage
Example 1: print out a simple object
var simpleObj = {
MyValue: 'test',
OtherValue: 'zzz',
NumberValue: 311,
MyArray: [1, 2, 3, 50, 60, 70]
};
const callbacks = {
processValue: (key, value, level, path, isObjectRoot, isArrayElement, cbSetValue) => {
console.log(level + ' ' + (path.length > 0 ? (path.join('.') + '.') : '') + key + ' = ' + value);
}
};
const jt = require('@tsmx/json-traverse');
jt.traverse(simpleObj, callbacks);
jt.traverse(simpleObj, callbacks, true);
Example 2: change values of an object
var simpleObj = {
MyValue: 'test',
OtherValue: 'zzz',
NumberValue: 311,
MyArray: [1, 2, 3, 50, 60, 70]
};
const callbacks = {
processValue: (key, value, level, path, isObjectRoot, isArrayElement, cbSetValue) => {
if (key.startsWith('My')) {
cbSetValue('MyNew-' + value);
}
if (isArrayElement && parseInt(value) > 50) {
cbSetValue(100 * parseInt(value));
}
}
};
const jt = require('@tsmx/json-traverse');
jt.traverse(simpleObj, callbacks);
Example 3: convert a more complex object to a collapsible HTML list
const htmlObj = {
MyArray: [0, 0],
ArrayInArry: [0, 1, ['two', 'three', [4, 5, 6]]],
MyNumber: 123,
MyString: 'test',
Child: {
ChildVal: 1,
SubChild: {
SubChildVal: 777
},
ChildArray: [1, 2, 66, 9, 900]
},
TrailingValue: 'testtesttest'
}
const callbacksHtmlList = {
processValue: (key, value, level, path, isObjectRoot, isArrayElement, cbSetValue) => {
if (isObjectRoot) {
console.log((' ').repeat(level) + ' <li class=\"caret\">Key: ' + key + '</li>')
}
else {
console.log((' ').repeat(level) + ' <li>Key: ' + key + ', Value: ' + value + '</li>')
};
},
enterLevel: (level, path) => {
if (level == 0) {
console.log('<ul>');
}
else {
console.log((' ').repeat(level) + '<ul class=\"nested\">');
};
},
exitLevel: (level, path) => { console.log((' ').repeat(level) + '</ul>'); }
};
const jt = require('@tsmx/json-traverse');
jt.traverse(htmlObj, callbacksHtmlList, true);
Key-features
- Define your callbacks for the following events:
processValue
: processing a traversed valueenterLevel
: entering a new nesting levelexitLevel
: leaving nesting level
- For every inspected value you will get rich meta-data
- key name
- level of nesting
isObjectRoot
flag to indicate if it's an object root (root of a nested object)isArrayElement
flag to indicate if it's an array item- full path to the key as an array of path elements
- Provides
cbSetValue
function to change any value in-place (directly in the traversed object) - Supports deep inspection of
- Subobjects
- Arrays
- Arrays-in-Arrays
- Subobjects-in-Arrays
- Optional array flattening (treat arrays as flat values)
API
traverse(obj, callbacks = null, flattenArray = false)
Traverse the obj
and apply the defined callbacks while traversing.
obj
Type: Object
The object to be traversed.
callbacks
Type: Object
Default: null
An Object containing the callback functions that should be applied while traversing obj
. Every callback is optional. The expected form is:
callbacks = {
processValue: (key, value, level, path, isObjectRoot, isArrayElement, cbSetValue) => {
},
enterLevel: (level, path) => {
},
exitLevel: (level, path) => {
}
};
processValue(key, value, level, path, isObjectRoot, isArrayElement, cbSetValue)
Defined callback function that is executed on each value when traversing the object. Receives the following input parameters:
key
Type: String
The key of the current value that is processed. If an array is deep-inspected the key for each processed item is _ + Index
(_0
, _1
, _2
,...).
value
Type: String
The actual value for key
.
level
Type: Number
The nesting level. 0
indicates the first level.
path
Type: Array
An array containing all keys that where passed to reach the current key/value pair. Example:
{
child: {
subchild: {
myvalue: 123;
}
}
}
When processing the value 123
with key myvalue
, path would be ['child', 'subchild' ]
.
For deep-inspected arrays the path would contain the name of the array itself whereas the key would be the index of the processed value. Example:
{
child: {
subchild: {
myvalues: [1, 2, 3]
}
}
}
When processing the array the keys would be _0
, _1
and _2
and the path would always be ['child', 'subchild', 'array']
.
isObjectRoot
Type: Boolean
true
if the currently processed key is the root of another sub-object. In our example:
{
child: {
subchild: {
myvalue: 123;
}
}
}
isObjectRoot
would be true
for the keys child
and subchild
.
isArrayElement
Type: Boolean
true
if the currently processed key is an item of an array.
cbSetValue(newValue)
Type: Function
Callback function receiving the newValue
that should replace the currently traversed value
.
Note: Setting a new value directly changes the traversed object! So if you need the original later on be sure to create a copy of the object first.
enterLevel(level, path)
Defined callback function that is executed on entering a new nesting level when traversing the object. Receives the following input parameters:
level
Type: Number
0-based index of the nesting level that is entered.
path
Type: Array
An array containing all keys that where passed to reach the current level that is entered.
exitLevel(level, path)
Defined callback function that is executed on leaving a nesting level when traversing the object. Receives the following input parameters:
level
Type: Number
0-based index of the nesting level that is exited.
path
Type: Array
An array containing all keys that where passed to reach the current level that is exited.
flattenArray
Type: Boolean
Default: false
If set to true
arrays will not be iterated but treated as one single value. The default is false
, where arrays are iterated and each entry is processed separately including deep-inspection, e.g. if the entry is an object or another array.