Gathering detailed insights and metrics for object-scan
Gathering detailed insights and metrics for object-scan
Gathering detailed insights and metrics for object-scan
Gathering detailed insights and metrics for object-scan
dyna-object-scan
Scan object deeply and safely
object-rewrite
Rewrite Object(s) in place using plugins.
@hyper.fun/fluentui-icon-scan-object-filled
👉 https://hyper.fun/c/fluentui-icon-scan-object-filled/2.0.0
@hyper.fun/fluentui-icon-scan-object-regular
👉 https://hyper.fun/c/fluentui-icon-scan-object-regular/2.0.0
Traverse object hierarchies using matching and callbacks.
npm install object-scan
Typescript
Module System
Min. Node Version
Node Version
NPM Version
JavaScript (96.77%)
HTML (2.92%)
Mustache (0.3%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
MIT License
176 Stars
3,554 Commits
16 Forks
5 Watchers
5 Branches
6 Contributors
Updated on Jun 14, 2025
Latest Version
20.0.1
Package Id
object-scan@20.0.1
Unpacked Size
158.99 kB
Size
27.03 kB
File Count
20
NPM Version
10.9.2
Node Version
22.13.1
Published on
Jan 29, 2025
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
36
Traverse object hierarchies using matching and callbacks.
Using npm:
$ npm i object-scan
In a browser:
<script type="module">
import objectScan from 'https://cdn.jsdelivr.net/npm/object-scan@<VERSION>/lib/index.min.js';
// do logic here
</script>
1import objectScan from 'object-scan'; 2 3const haystack = { a: { b: { c: 'd' }, e: { f: 'g' } } }; 4objectScan(['a.*.f'], { joined: true })(haystack); 5// => [ 'a.e.f' ]
A needle expression specifies one or more paths to an element (or a set of elements) in a JSON structure. Paths use the dot notation.
store.book[0].title
The matching syntax is fully validated and bad input will throw a syntax error. The following syntax is supported:
Rectangular brackets for array path matching.
Examples:
['[2]']
(exact in array) 1const haystack = [0, 1, 2, 3, 4]; 2objectScan(['[2]'], { joined: true })(haystack); 3// => [ '[2]' ]
['[1]']
(no match in object) 1const haystack = { 0: 'a', 1: 'b', 2: 'c' }; 2objectScan(['[1]'], { joined: true })(haystack); 3// => []
Property name for object property matching.
Examples:
['foo']
(exact in object) 1const haystack = { foo: 0, bar: 1 }; 2objectScan(['foo'], { joined: true })(haystack); 3// => [ 'foo' ]
['1']
(no match in array) 1const haystack = [0, 1, 2, 3, 4]; 2objectScan(['1'], { joined: true })(haystack); 3// => []
The following characters have special meaning when not escaped:
*
: Match zero or more character+
: Match one or more character?
: Match exactly one character\
: Escape the subsequent characterCan be used with Array and Object selector.
Examples:
['foo*']
(starting with `foo`) 1const haystack = { foo: 0, foobar: 1, bar: 2 }; 2objectScan(['foo*'], { joined: true })(haystack); 3// => [ 'foobar', 'foo' ]
['*']
(top level) 1const haystack = { a: { b: 0, c: 1 }, d: 2 }; 2objectScan(['*'], { joined: true })(haystack); 3// => [ 'd', 'a' ]
['[?5]']
(two digit ending in five) 1const haystack = [...Array(30).keys()]; 2objectScan(['[?5]'], { joined: true })(haystack); 3// => [ '[25]', '[15]' ]
['a.+.c']
(nested) 1const haystack = { a: { b: { c: 0 }, d: { f: 0 } } }; 2objectScan(['a.+.c'], { joined: true })(haystack); 3// => [ 'a.b.c' ]
['a.\\+.c']
(escaped) 1const haystack = { a: { b: { c: 0 }, '+': { c: 0 } } }; 2objectScan(['a.\\+.c'], { joined: true })(haystack); 3// => [ 'a.\\+.c' ]
Regex are defined by using parentheses.
Can be used with Array and Object selector.
Examples:
['(^foo)']
(starting with `foo`) 1const haystack = { foo: 0, foobar: 1, bar: 2 }; 2objectScan(['(^foo)'], { joined: true })(haystack); 3// => [ 'foobar', 'foo' ]
['[(5)]']
(containing `5`) 1const haystack = [...Array(20).keys()]; 2objectScan(['[(5)]'], { joined: true })(haystack); 3// => [ '[15]', '[5]' ]
['[(^[01]$)]']
(`[0]` and `[1]`) 1const haystack = ['a', 'b', 'c', 'd']; 2objectScan(['[(^[01]$)]'], { joined: true })(haystack); 3// => [ '[1]', '[0]' ]
['[(^[^01]$)]']
(other than `[0]` and `[1]`) 1const haystack = ['a', 'b', 'c', 'd']; 2objectScan(['[(^[^01]$)]'], { joined: true })(haystack); 3// => [ '[3]', '[2]' ]
Or Clauses are defined by using curley brackets.
Can be used with Array and Object selector and Arbitrary Depth matching.
Examples:
['[{0,1}]']
(`[0]` and `[1]`) 1const haystack = ['a', 'b', 'c', 'd']; 2objectScan(['[{0,1}]'], { joined: true })(haystack); 3// => [ '[1]', '[0]' ]
['{a,d}.{b,f}']
(`a.b`, `a.f`, `d.b` and `d.f`) 1const haystack = { a: { b: 0, c: 1 }, d: { e: 2, f: 3 } }; 2objectScan(['{a,d}.{b,f}'], { joined: true })(haystack); 3// => [ 'd.f', 'a.b' ]
There are two types of arbitrary depth matching:
**
: Matches zero or more nestings++
: Matches one or more nestingsCan be combined with Regex and Or Clause by prepending.
Examples:
['a.**']
(zero or more nestings under `a`) 1const haystack = { a: { b: 0, c: 0 } }; 2objectScan(['a.**'], { joined: true })(haystack); 3// => [ 'a.c', 'a.b', 'a' ]
['a.++']
(one or more nestings under `a`) 1const haystack = { a: { b: 0, c: 0 } }; 2objectScan(['a.++'], { joined: true })(haystack); 3// => [ 'a.c', 'a.b' ]
['**(1)']
(all containing `1` at every level) 1const haystack = { 1: { 1: ['c', 'd'] }, 510: 'e', foo: { 1: 'f' } }; 2objectScan(['**(1)'], { joined: true })(haystack); 3// => [ '510', '1.1[1]', '1.1', '1' ]
To match a nested path recursively, combine Arbitrary Depth matching with an Or Clause.
There are two types of nested path matching:
**{...}
: Matches path(s) in Or Clause zero or more times++{...}
: Matches path(s) in Or Clause one or more timesExamples:
['++{[0][1]}']
(`cyclic path`) 1const haystack = [[[[0, 1], [1, 2]], [[3, 4], [5, 6]]], [[[7, 8], [9, 10]], [[11, 12], [13, 14]]]]; 2objectScan(['++{[0][1]}'], { joined: true })(haystack); 3// => [ '[0][1][0][1]', '[0][1]' ]
['++{[0],[1]}']
(`nested or`) 1const haystack = [[0, 1, 2], [3, 4, 5], [6, 7, 8]]; 2objectScan(['++{[0],[1]}'], { joined: true })(haystack); 3// => [ '[1][1]', '[1][0]', '[1]', '[0][1]', '[0][0]', '[0]' ]
['**{[*]}']
(`traverse only array`) 1const haystack = [[[{ a: [1] }], [2]]]; 2objectScan(['**{[*]}'], { joined: true })(haystack); 3// => [ '[0][1][0]', '[0][1]', '[0][0][0]', '[0][0]', '[0]' ]
['**{*}']
(`traverse only object`) 1const haystack = { a: [0, { b: 1 }], c: { d: 2 } }; 2objectScan(['**{*}'], { joined: true })(haystack); 3// => [ 'c.d', 'c', 'a' ]
['a.**{b.c}']
(`zero or more times`) 1const haystack = { a: { b: { c: { b: { c: 0 } } } } }; 2objectScan(['a.**{b.c}'], { joined: true })(haystack); 3// => [ 'a.b.c.b.c', 'a.b.c', 'a' ]
['a.++{b.c}']
(`one or more times`) 1const haystack = { a: { b: { c: { b: { c: 0 } } } } }; 2objectScan(['a.++{b.c}'], { joined: true })(haystack); 3// => [ 'a.b.c.b.c', 'a.b.c' ]
To exclude a path, use exclamation mark.
Examples:
['{a,b},!a']
(only `b`) 1const haystack = { a: 0, b: 1 }; 2objectScan(['{a,b},!a'], { 3 joined: true, 4 strict: false 5})(haystack); 6// => [ 'b' ]
['**,!**.a']
(all except ending in `a`) 1const haystack = { a: 0, b: { a: 1, c: 2 } }; 2objectScan(['**,!**.a'], { joined: true })(haystack); 3// => [ 'b.c', 'b' ]
['[*]', '[!(^[01]$)]']
(exclude with regex) 1const haystack = ['a', 'b', 'c', 'd']; 2objectScan(['[*]', '[!(^[01]$)]'], { joined: true })(haystack); 3// => [ '[3]', '[2]' ]
The following characters are considered special and need to
be escaped using \
, if they should be matched in a key:
[
, ]
, {
, }
, (
, )
, ,
, .
, !
, ?
, *
, +
and \
.
Examples:
['\\[1\\]']
(special object key) 1const haystack = { '[1]': 0 }; 2objectScan(['\\[1\\]'], { joined: true })(haystack); 3// => [ '\\[1\\]' ]
Needles can be passed as arrays, consisting of integers
and strings
.
When given as arrays, then needles:
integers
and object keys with strings
This syntax allows for key
result of object-scan to be passed back into itself.
Be advised that matchedBy
and similar contain the original needles and not copies.
Array needles work similarly to how they work in _.get.
Examples:
[['a', 0, 'b']]
(mixed path) 1const haystack = { a: [{ b: 0 }] }; 2objectScan([['a', 0, 'b']], { joined: true })(haystack); 3// => [ 'a[0].b' ]
[['a.b', 0]]
(implicit escape) 1const haystack = { 'a.b': [0], a: { b: [1] } }; 2objectScan([['a.b', 0]], { 3 joined: true, 4 rtn: 'value' 5})(haystack); 6// => [ 0 ]
[['a', 0, 'b'], ['a', 1, 'b'], 'a[*].b']
(mixed needles) 1const haystack = { a: [{ b: 0 }, { b: 0 }] }; 2objectScan([['a', 0, 'b'], ['a', 1, 'b'], 'a[*].b'], { 3 joined: true, 4 rtn: 'matchedBy' 5})(haystack); 6// => [ [ [ 'a', 1, 'b' ], 'a[*].b' ], [ [ 'a', 0, 'b' ], 'a[*].b' ] ]
[['a', 'b']]
(useArraySelector=false) 1const haystack = { a: [{ b: 0 }, { b: 0 }] }; 2objectScan([['a', 'b']], { 3 joined: true, 4 useArraySelector: false 5})(haystack); 6// => [ 'a[1].b', 'a[0].b' ]
Fn({ key, value, ... })
where:
key
: key that callback is invoked for (respects joined
option).value
: value for key.entry
: entry consisting of [key
, value
].property
: current parent property.gproperty
: current grandparent property.parent
: current parent.gparent
: current grandparent.parents
: array of form [parent, grandparent, ...]
.isMatch
: true iff last targeting needle exists and is non-excluding.matchedBy
: all non-excluding needles targeting key.excludedBy
: all excluding needles targeting key.traversedBy
: all needles involved in traversing key.isCircular
: true iff value
contained in parents
isLeaf
: true iff value
can not be traverseddepth
: length of key
result
: intermittent result as defined by rtn
getKey(joined?: boolean)
: function that returns key
getValue
: function that returns value
getEntry(joined?: boolean)
: function that returns entry
getProperty
: function that returns property
getGproperty
: function that returns gproperty
getParent
: function that returns parent
getGparent
: function that returns gparent
getParents
: function that returns parents
getIsMatch
: function that returns isMatch
getMatchedBy
: function that returns matchedBy
getExcludedBy
: function that returns excludedBy
getTraversedBy
: function that returns traversedBy
getIsCircular
: function that returns isCircular
getIsLeaf
: function that returns isLeaf
getDepth
: function that returns depth
getResult
: function that returns result
context
: as passed into the searchNotes on Performance
if (isMatch) { getParents() ... }
.Search Context
Examples:
['**.{c,d,e}']
(search context) 1const haystack = { a: { b: { c: 2, d: 11 }, e: 7 } }; 2objectScan(['**.{c,d,e}'], { 3 joined: true, 4 filterFn: ({ value, context }) => { context.sum += value; } 5})(haystack, { sum: 0 }); 6// => { sum: 20 }
Type: function
Default: undefined
When defined, this callback is invoked for every match. If false
is returned, the current key is excluded from the result.
The return value of this callback has no effect when a search context is provided.
Can be used to do processing as matching keys are traversed.
Invoked in same order as matches would appear in result.
For more information on invocation order, please refer to Section Traversal Order.
This method is conceptually similar to Array.filter().
Examples:
['**']
(filter function) 1const haystack = { a: 0, b: 'bar' }; 2objectScan(['**'], { 3 joined: true, 4 filterFn: ({ value }) => typeof value === 'string' 5})(haystack); 6// => [ 'b' ]
Type: function
Default: undefined
When defined, this callback is invoked for every key that is traversed by
the search. If true
is returned, all keys nested under the current key are
skipped in the search and from the final result.
Note that breakFn
is invoked before the corresponding filterFn
might be invoked.
For more information on invocation order, please refer to Section Traversal Order.
Examples:
['**']
(break function) 1const haystack = { a: { b: { c: 0 } } }; 2objectScan(['**'], { 3 joined: true, 4 breakFn: ({ key }) => key === 'a.b' 5})(haystack); 6// => [ 'a.b', 'a' ]
Type: function
Default: undefined
When defined, this function is called before traversal as beforeFn(state = { haystack, context })
.
If a value other than undefined
is returned from beforeFn
,
that value is written to state.haystack
before traversal.
The content of state
can be modified in the function.
After beforeFn
has executed, the traversal happens using state.haystack
and state.context
.
The content in state
can be accessed in afterFn
.
Note however that the key result
is being overwritten.
Examples:
['**']
(combining haystack and context) 1const haystack = { a: 0 }; 2objectScan(['**'], { 3 joined: true, 4 beforeFn: ({ haystack: h, context: c }) => [h, c], 5 rtn: 'key' 6})(haystack, { b: 0 }); 7// => [ '[1].b', '[1]', '[0].a', '[0]' ]
['**']
(pre-processing haystack) 1const haystack = { a: 0, b: 1 }; 2objectScan(['**'], { 3 joined: true, 4 beforeFn: ({ haystack: h }) => Object.keys(h), 5 rtn: ['key', 'value'] 6})(haystack); 7// => [ [ '[1]', 'b' ], [ '[0]', 'a' ] ]
Type: function
Default: undefined
When defined, this function is called after traversal as afterFn(state = { result, haystack, context })
.
Additional information written to state
in beforeFn
is available in afterFn
.
The content of state
can be modified in the function. In particular the key state.result
can be updated.
If a value other than undefined
is returned from afterFn
, that value is written to state.result
.
After beforeFn
has executed, the key state.result
is returned as the final result.
Examples:
['**']
(returning count plus context) 1const haystack = { a: 0 }; 2objectScan(['**'], { 3 afterFn: ({ result, context }) => result + context, 4 rtn: 'count' 5})(haystack, 5); 6// => 6
['**']
(post-processing result) 1const haystack = { a: 0, b: 3, c: 4 }; 2objectScan(['**'], { 3 afterFn: ({ result }) => result.filter((v) => v > 3), 4 rtn: 'value' 5})(haystack); 6// => [ 4 ]
['**']
(pass data from beforeFn to afterFn) 1const haystack = {}; 2objectScan(['**'], { 3 beforeFn: (state) => { /* eslint-disable no-param-reassign */ state.custom = 7; }, 4 afterFn: (state) => state.custom 5})(haystack); 6// => 7
Type: function
Default: undefined
This function has the same signature as the callback functions. When defined it is expected to return a function
or undefined
.
The returned value is used as a comparator to determine the traversal order of any object
keys.
This works together with the reverse
option.
Please refer to Section Traversal Order for more information.
Examples:
['**']
(simple sort) 1const haystack = { a: 0, c: 1, b: 2 }; 2objectScan(['**'], { 3 joined: true, 4 compareFn: () => (k1, k2) => k1.localeCompare(k2), 5 reverse: false 6})(haystack); 7// => [ 'a', 'b', 'c' ]
Type: boolean
Default: true
When set to true
, the traversal is performed in reverse order. This means breakFn
is executed in reverse post-order and
filterFn
in reverse pre-order. Otherwise breakFn
is executed in pre-order and filterFn
in post-order.
When reverse
is true
the traversal is delete-safe. I.e. property
can be deleted / spliced from parent
object / array in filterFn
.
Please refer to Section Traversal Order for more information.
Examples:
['**']
(breakFn, reverse true) 1const haystack = { f: { b: { a: {}, d: { c: {}, e: {} } }, g: { i: { h: {} } } } }; 2objectScan(['**'], { 3 breakFn: ({ isMatch, property, context }) => { if (isMatch) { context.push(property); } }, 4 reverse: true 5})(haystack, []); 6// => [ 'f', 'g', 'i', 'h', 'b', 'd', 'e', 'c', 'a' ]
['**']
(filterFn, reverse true) 1const haystack = { f: { b: { a: {}, d: { c: {}, e: {} } }, g: { i: { h: {} } } } }; 2objectScan(['**'], { 3 filterFn: ({ property, context }) => { context.push(property); }, 4 reverse: true 5})(haystack, []); 6// => [ 'h', 'i', 'g', 'e', 'c', 'd', 'a', 'b', 'f' ]
['**']
(breakFn, reverse false) 1const haystack = { f: { b: { a: {}, d: { c: {}, e: {} } }, g: { i: { h: {} } } } }; 2objectScan(['**'], { 3 breakFn: ({ isMatch, property, context }) => { if (isMatch) { context.push(property); } }, 4 reverse: false 5})(haystack, []); 6// => [ 'f', 'b', 'a', 'd', 'c', 'e', 'g', 'i', 'h' ]
['**']
(filterFn, reverse false) 1const haystack = { f: { b: { a: {}, d: { c: {}, e: {} } }, g: { i: { h: {} } } } }; 2objectScan(['**'], { 3 filterFn: ({ property, context }) => { context.push(property); }, 4 reverse: false 5})(haystack, []); 6// => [ 'a', 'c', 'e', 'd', 'b', 'h', 'i', 'g', 'f' ]
Type: boolean
Default: false
When set to false
, all targeted keys are traversed and matched
in the order determined by the compareFn
and reverse
option.
When set to true
, all targeted keys are traversed and matched
in the order determined by the corresponding needles,
falling back to the above ordering.
Note that this option is constraint by the depth-first search approach.
Examples:
['c', 'a', 'b']
(order by needle) 1const haystack = { a: 0, b: 1, c: 1 }; 2objectScan(['c', 'a', 'b'], { 3 joined: true, 4 orderByNeedles: true 5})(haystack); 6// => [ 'c', 'a', 'b' ]
['b', '*']
(fallback reverse) 1const haystack = { a: 0, b: 1, c: 1 }; 2objectScan(['b', '*'], { 3 joined: true, 4 reverse: true, 5 orderByNeedles: true 6})(haystack); 7// => [ 'b', 'c', 'a' ]
['b', '*']
(fallback not reverse) 1const haystack = { a: 0, b: 1, c: 1 }; 2objectScan(['b', '*'], { 3 joined: true, 4 reverse: false, 5 orderByNeedles: true 6})(haystack); 7// => [ 'b', 'a', 'c' ]
['a', 'b.c', 'd']
(nested match) 1const haystack = { a: 0, b: { c: 1 }, d: 2 }; 2objectScan(['a', 'b.c', 'd'], { 3 joined: true, 4 orderByNeedles: true 5})(haystack); 6// => [ 'a', 'b.c', 'd' ]
['b', 'a', 'b.c', 'd']
(matches traverse first) 1const haystack = { a: 0, b: { c: 1 }, d: 2 }; 2objectScan(['b', 'a', 'b.c', 'd'], { 3 joined: true, 4 orderByNeedles: true 5})(haystack); 6// => [ 'b.c', 'b', 'a', 'd' ]
Type: boolean
Default: false
When set to true
the traversal immediately returns after the first match.
Examples:
['a', 'b']
(only return first property) 1const haystack = { a: 0, b: 1 }; 2objectScan(['a', 'b'], { 3 rtn: 'property', 4 abort: true 5})(haystack); 6// => 'b'
['[0]', '[1]']
(abort changes count) 1const haystack = ['a', 'b']; 2objectScan(['[0]', '[1]'], { 3 rtn: 'count', 4 abort: true 5})(haystack); 6// => 1
Type: string
or array
or function
Default: dynamic
Defaults to key
when search context is undefined and to context
otherwise.
Can be explicitly set as a string
:
context
: search context is returnedkey
: as passed into filterFn
value
: as passed into filterFn
entry
: as passed into filterFn
property
: as passed into filterFn
gproperty
: as passed into filterFn
parent
: as passed into filterFn
gparent
: as passed into filterFn
parents
: as passed into filterFn
isMatch
: as passed into filterFn
matchedBy
: as passed into filterFn
excludedBy
: as passed into filterFn
traversedBy
: as passed into filterFn
isCircular
: as passed into filterFn
isLeaf
: as passed into filterFn
depth
: as passed into filterFn
bool
: returns true iff a match is foundcount
: returns the match countsum
: returns the match sumWhen set to array
, can contain any of the above except context
, bool
, count
and sum
.
When set to function
, called with callback signature for every match. Returned value is added to the result.
When abort is set to true
and rtn is not context
, bool
, count
or sum
,
the first entry of the result or undefined is returned.
Examples:
['[*]']
(return values) 1const haystack = ['a', 'b', 'c']; 2objectScan(['[*]'], { rtn: 'value' })(haystack); 3// => [ 'c', 'b', 'a' ]
['foo[*]']
(return entries) 1const haystack = { foo: ['bar'] }; 2objectScan(['foo[*]'], { rtn: 'entry' })(haystack); 3// => [ [ [ 'foo', 0 ], 'bar' ] ]
['a.b.c', 'a']
(return properties) 1const haystack = { a: { b: { c: 0 } } }; 2objectScan(['a.b.c', 'a'], { rtn: 'property' })(haystack); 3// => [ 'c', 'a' ]
['a.b', 'a.c']
(checks for any match, full traversal) 1const haystack = { a: { b: 0, c: 1 } }; 2objectScan(['a.b', 'a.c'], { rtn: 'bool' })(haystack); 3// => true
['**']
(return not provided context) 1const haystack = { a: 0 }; 2objectScan(['**'], { rtn: 'context' })(haystack); 3// => undefined
['a.b.{c,d}']
(return keys with context passed) 1const haystack = { a: { b: { c: 0, d: 1 } } }; 2objectScan(['a.b.{c,d}'], { rtn: 'key' })(haystack, []); 3// => [ [ 'a', 'b', 'd' ], [ 'a', 'b', 'c' ] ]
['a.b.{c,d}']
(return custom array) 1const haystack = { a: { b: { c: 0, d: 1 } } }; 2objectScan(['a.b.{c,d}'], { rtn: ['property', 'value'] })(haystack, []); 3// => [ [ 'd', 1 ], [ 'c', 0 ] ]
['**']
(return value plus one) 1const haystack = { a: { b: { c: 0, d: 1 } } }; 2objectScan(['**'], { 3 filterFn: ({ isLeaf }) => isLeaf, 4 rtn: ({ value }) => value + 1 5})(haystack); 6// => [ 2, 1 ]
['**']
(return sum) 1const haystack = { a: { b: { c: -2, d: 1 }, e: [3, 7] } }; 2objectScan(['**'], { 3 filterFn: ({ value }) => typeof value === 'number', 4 rtn: 'sum' 5})(haystack); 6// => 9
Type: boolean
Default: false
Keys are returned as a string when set to true
instead of as a list.
Setting this option to true
will negatively impact performance.
This setting can be overwritten by using the getter method getKey()
or getEntry()
.
Note that _.get and _.set fully support lists.
Examples:
['[*]', '[*].foo']
(joined) 1const haystack = [0, 1, { foo: 'bar' }]; 2objectScan(['[*]', '[*].foo'], { joined: true })(haystack); 3// => [ '[2].foo', '[2]', '[1]', '[0]' ]
['[*]', '[*].foo']
(not joined) 1const haystack = [0, 1, { foo: 'bar' }]; 2objectScan(['[*]', '[*].foo'])(haystack); 3// => [ [ 2, 'foo' ], [ 2 ], [ 1 ], [ 0 ] ]
['**.c']
(joined, getKey) 1const haystack = { a: { b: { c: 0 } } }; 2objectScan(['**.c'], { 3 joined: true, 4 rtn: ({ getKey }) => [getKey(true), getKey(false), getKey()] 5})(haystack); 6// => [ [ 'a.b.c', [ 'a', 'b', 'c' ], 'a.b.c' ] ]
['**.c']
(not joined, getEntry) 1const haystack = { a: { b: { c: 0 } } }; 2objectScan(['**.c'], { rtn: ({ getEntry }) => [getEntry(true), getEntry(false), getEntry()] })(haystack); 3// => [ [ [ 'a.b.c', 0 ], [ [ 'a', 'b', 'c' ], 0 ], [ [ 'a', 'b', 'c' ], 0 ] ] ]
Type: boolean
Default: true
When set to false
, no array selectors should be used in any needles and arrays are automatically traversed.
Note that the results still include the array selectors.
Examples:
['a', 'b.d']
(automatic array traversal) 1const haystack = [{ a: 0 }, { b: [{ c: 1 }, { d: 2 }] }]; 2objectScan(['a', 'b.d'], { 3 joined: true, 4 useArraySelector: false 5})(haystack); 6// => [ '[1].b[1].d', '[0].a' ]
['']
(top level array matching) 1const haystack = [{ a: 0 }, { b: 1 }]; 2objectScan([''], { 3 joined: true, 4 useArraySelector: false 5})(haystack); 6// => [ '[1]', '[0]' ]
Type: boolean
Default: true
When set to true
, errors are thrown when:
Examples:
['a.b', 'a.b']
(identical) 1const haystack = []; 2objectScan(['a.b', 'a.b'], { joined: true })(haystack); 3// => 'Error: Redundant Needle Target: "a.b" vs "a.b"'
['a.{b,b}']
(identical, same needle) 1const haystack = []; 2objectScan(['a.{b,b}'], { joined: true })(haystack); 3// => 'Error: Redundant Needle Target: "a.{b,b}" vs "a.{b,b}"'
['a.b', 'a.**']
(invalidates previous) 1const haystack = []; 2objectScan(['a.b', 'a.**'], { joined: true })(haystack); 3// => 'Error: Needle Target Invalidated: "a.b" by "a.**"'
['**.!**']
(consecutive recursion) 1const haystack = []; 2objectScan(['**.!**'], { joined: true })(haystack); 3// => 'Error: Redundant Recursion: "**.!**"'
This library has a similar syntax and can perform similar tasks to jsonpath or jmespath. But instead of querying an object hierarchy, it focuses on traversing it. Hence, it is designed around handling multiple paths in a single traversal. No other library doing this is currently available.
While nimma provides the ability to traverse multiple paths, it doesn't do it in a single traversal.
A one-to-one comparison with other libraries is difficult due to difference in functionality,
but it can be said that object-scan
is more versatile at similar performance.
No vulnerabilities found.
Reason
no binaries found in the repo
Reason
license file detected
Details
Reason
Found 9/18 approved changesets -- score normalized to 5
Reason
6 existing vulnerabilities detected
Details
Reason
0 commit(s) and 3 issue activity found in the last 90 days -- score normalized to 2
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
Reason
project is not fuzzed
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Score
Last Scanned on 2025-07-07
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More