JavaScript library to dig nested object returned from api.
If api endpoint returns,
{
animal: {
mammal: {
moles: [
{
name: 'parent1',
children: [{ name: 'child1-1' }, { name: 'child1-2' }]
},
{
name: 'parent2',
children: [{ name: 'child2-1' }, { name: 'child2-2' }]
}
]
}
}
}
and you want to get ['child1-2', 'child1-2', 'child2-1', 'child2-2']
, with pure javascript,
object.animal.mammal.moles.map(mole => mole.children.map(child => child.name)).flat()
// or
object.animal.mammal.moles.flatMap(mole => mole.children.map(child => child.name))
// => ['child1-2', 'child1-2', 'child2-1', 'child2-2']
This code does not show the composition of the object, so it is difficult to understand how is the object
.
On the other hand, with this library,
import { dig, $$target, $$array } from 'smart-mole'
dig(obj, {
animal: {
mammal: {
moles: $$array({
children: $$array({ name: $$target })
})
}
}
})
// => ['child1-2', 'child1-2', 'child2-1', 'child2-2']
npm i smart-mole
or
yarn add smart-mole
import { dig } from smart-mole
dig(<target_object>, <target_map>, <target_marker>)
argument | description |
---|---|
target_object | object or array you want to dig |
target_map | object or array presenting target location, by marking target with target_marker |
target_marker | optional, default is $$target which is a constant of **target** |
Note that target_marker should NOT be included in any keys of <target_object>. if included, it will cause a bug. Bad example:
const object = { '**target**': { bar: 1 } }
dig(object, { '**target**': { bar: $$target } }
You should change target_marker like this.
dig(object, { '**target**': { bar: '***' } }, '***')
- Convert target_map to JSON string.
JSON.stringify(target_map)
// => {"animal":{"mammal":{"moles":[{"name":"_"},{"name":"*"}]}}}
- From the result of 1, search a object or array that includes target_marker.
{"animal":{"mammal":{"moles":[{"name":"_"},{"name":"*"}]}}}
// ^^^^^^^^^^^^
=> {"name":"*"}
- From the result of 2. get the key and memorize it.
{"name":"*"}
=> 'name'
// keys <- 'name'
- replace the result of 2. by target_marker.
{"animal":{"mammal":{"moles":[{"name":"_"},{"name":"*"}]}}}
// ^^^^^^^^^^^^
// replace => {"animal":{"mammal":{"moles":[{"name":"_"},"*"]}}}
- From the result of 4, search a object or array that includes target_marker(like 2.)
{"animal":{"mammal":{"moles":[{"name":"_"},"*"]}}}
// ^^^^^^^^^^^^^^^^^^
- get the key(or index) and memorize it.
[{"name":"_"},"*"]
=> 1 (index)
// keys <- 1
// keys: ['name', 1]
- repeat until the result of replacement is same as target_marker.
keys: ['name', 1, 'moles', 'mammal', 'animal']
- Using keys, dig a target object
let value = object
for (const key of keys.reverse()) {
value = value[key]
}
value // => 'Don Resetti' (same as object.animal.mammal.moles[1].name)
You should just use Destructuring assignment in some case.
/*
object is {
animal: {
mamal: {
moles: [
{ name: 'Mr. Resetti' },
{ name: 'Don Resetti' }
]
}
}
}
*/
// you can get 'Don Resetti' by the folloing method
const { animal: { mamal: { moles: [, { name }] } } } = object
console.log(name) // => 'Don Resetti'