Object property paths with wildcards and regexps.

Get/set object properties using:

Dot-delimited paths: foo.bar.0.baz Wildcards: foo.*, **.bar Regexps: foo./ba?/ Slices: foo.0:2 Unions: foo bar baz Install

npm install wild-wild-path

This package works in both Node.js >=16.17.0 and browsers.

This is an ES module. It must be loaded using an import or import() statement, not require(). If TypeScript is used, it must be configured to output ES modules, not CommonJS.

API Methods get(target, query, options?)

target: Target
query: Query
options: Options?
Return value: any | undefined

Return the first property matching the query.

const target = { settings: { colors: ['red', 'blue'] } } get(target, 'settings.colors.0') // 'red' get(target, ['settings', 'colors', 0]) // 'red' has(target, query, options?)

target: Target
query: Query
options: Options?
Return value: boolean

Return whether the query matches any property.

const target = { settings: { lastName: undefined, colors: ['red', 'blue'] } } has(target, 'settings.firstName') // false has(target, ['settings', 'firstName']) // false has(target, 'settings.lastName') // true list(target, query, options?)

target: Target
query: Query
options: Options?
Return value: any[]

Return all properties matching the query, as an array.

const target = { userOne: { firstName: 'John', lastName: 'Doe', age: 72 }, userTwo: { firstName: 'Alice', colors: ['red', 'blue', 'yellow'] }, } list(target, 'userOne.firstName userTwo.colors.0') // ['John', 'red'] list(target, [ ['userOne', 'firstName'], ['userTwo', 'colors', 0], ]) // ['John', 'red'] list(target, 'userOne./Name/') // ['John', 'Doe'] list(target, ['userOne', /Name/]) // ['John', 'Doe'] list(target, 'userTwo.colors.*') // ['red', 'blue', 'yellow'] list(target, 'userTwo.colors.0:2') // ['red', 'blue'] list(target, '**.firstName') // ['John', 'Alice'] list(target, 'userOne.*', { entries: true }) // [ // { value: 'John', path: ['userOne', 'firstName'], missing: false }, // { value: 'Doe', path: ['userOne', 'lastName'], missing: false }, // { value: 72, path: ['userOne', 'age'], missing: false }, // ] iterate(target, query, options?)

target: Target
query: Query
options: Options?
Return value: Iterable<any>

Return all properties matching the query, as an iterable. This is slower than list() but uses less memory.

const target = { settings: { colors: ['red', 'blue'] } } for (const color of iterate(target, 'settings.colors.*')) { console.log(color) // 'red', 'blue' } set(target, query, value, options?)

target: Target
query: Query
value: any
options: Options?
Return value: Target

Sets all properties matching the query. The return value is a deep clone unless the mutate option is true.

const target = { colors: ['red', 'blue'] } set(target, 'colors.0', 'yellow') // ['yellow', 'blue'] set(target, ['colors', 0], 'yellow') // ['yellow', 'blue'] set(target, 'colors.-1', 'yellow') // ['red', 'yellow'] set(target, 'colors.-0', 'yellow') // ['red', 'blue', 'yellow'] set(target, 'colors.*', 'yellow') // ['yellow', 'yellow'] set({}, 'user.0.color', 'red') // { user: [{ color: 'red' }] } set({}, 'user.0.color', 'red', { missing: false }) // {} remove(target, query, options?)

target: Target
query: Query
options: Options?
Return value: Target

Delete all properties matching the query. The return value is a deep clone unless the mutate option is true.

const target = { user: { firstName: 'John', lastName: 'Doe', age: 72 } } remove(target, 'user.lastName') // { user: { firstName: 'John', age: 72 } } remove(target, 'user./Name/') // { user: { age: 72 } } remove(target, ['user', /Name/]) // { user: { age: 72 } } Functional utilities

wild-wild-utils is a separate library which provides with additional, higher-level methods: map(), merge(), push(), unshift(), find(), pick(), include(), exclude(), flatten().

Target

The target value must be an object or an array.

Queries

There are two equivalent formats for queries: strings and arrays.

Query strings are friendlier to CLI usage, more expressive, and easier to serialize. Query arrays are friendlier to programmatic usage, and faster. Also, they do not require escaping, so they should be used when the input is dynamic or user-provided to prevent injection attacks. Query strings Deep properties

# Deep properties of objects or arrays. # Dots are used for array indices, not brackets. # Symbol properties are always ignored. user.colors.0 Unions

# Unions ("or") of queries are space-delimited. # The string must not be empty. colors name age Wildcards

# Shallow wildcards target all properties/items of a single object/array user.* # Deep wildcards target all properties/items of 0, 1 or many objects/arrays user.** **.colors Regexps

# Regexps match property names user./name/ # Flags can be used, e.g. to make it case-insensitive user./name/i # ^ $ must be used to match from the beginning or until the end user./^name$/i Arrays indices

# Array indices are integers user.colors.0 # Array indices can be negative. # -1 is the last item. # -0 is the item after it, which can be used to append. user.colors.-1 Array slices

# Array slices. Goes from the start (included) to the end index (excluded). user.colors.0:2 # The start index defaults to 0, i.e. the beginning user.colors.:2 # The end index defaults to -0, i.e. the end user.colors.0: user.colors.: Escaping

# Dots, spaces and backslashes in property names must be escaped name\\ with\\ spaces name\\.with\\.dots name\\\\with\\\\backslashes # Ambiguous property names must be escaped with a backslash at the beginning. # This includes properties that: # - Are integers but are not array elements # - Have multiple slashes and start with one name.\\0 name.\\/not_a_regexp/ Root and empty strings

# A leading dot can optionally be used. It is ignored. user.colors .user.colors # Root value . # Empty string properties user..colors Query arrays Deep properties

// Deep properties of objects or arrays. // Symbol properties are always ignored. ['user', 'colors', 0] Unions

// Unions ("or") of queries are arrays of arrays. // There must be at least one item. [['colors'], ['name'], ['age']] Wildcards

// Shallow wildcards target all properties/items of a single object/array ['user', { type: 'any' }] // Deep wildcards target all properties/items of 0, 1 or many objects/arrays ['user', { type: 'anyDeep' }] [{ type: 'anyDeep' }, 'colors'] Regexps

// Regexps match property names ['user', /name/] // Flags can be used, e.g. to make it case-insensitive ['user', /name/i] // ^ $ must be used to match from the beginning or until the end ['user', /^name$/i] Arrays indices

// Array indices are integers, not strings ['user', 'colors', 0] // Array indices can be negative. // -1 is the last item. // -0 is the item after it, which can be used to append. ['user', 'colors', -1] Array slices

// Array slices. Goes from the start (included) to the end index (excluded). ['user', 'colors', { type: 'slice', from: 0, to: 2 }] // The start index defaults to 0, i.e. the beginning ['user', 'colors', { type: 'slice', to: 2 }] // The end index defaults to -0, i.e. the end ['user', 'colors', { type: 'slice', from: 0 }] ['user', 'colors', { type: 'slice' }] Escaping

// Escaping is not necessary with query arrays ['name with spaces'] ['name.with.dots'] ['name\\with\\backslashes'] ['name', '0'] ['name', '/not_a_regexp/'] Root and empty strings

// Root value [] // Empty string properties ['user', '', 'colors'] Paths

A "path" is any query using only property names and positive array indices. This excludes negative indices, slices, wildcards, regexps and unions.

Paths are returned by the entries option.

# Path string user.colors.0

// Path array ['user', 'colors', 0] Conversions and comparisons

wild-wild-parser can be used to convert between both formats, or to compare queries.

Undefined values

Object properties with a defined key but an undefined value are not ignored. However, object properties without any defined key are ignored. The has() method, missing option and entries option can be used to distinguish those.

const target = { name: undefined } has(target, 'name') // true has(target, 'colors') // false get(target, 'name') // undefined get(target, 'colors') // undefined get(target, 'name', { entries: true, missing: true }) // { value: undefined, path: ['name'], missing: false } get(target, 'colors', { entries: true, missing: true }) // { value: undefined, path: ['colors'], missing: true } list(target, '*') // [undefined] list(target, '*', { entries: true }) // [{ value: undefined, path: ['name'], missing: false }] Options

Options are optional plain objects.

mutate

Methods: set(), remove()
Type: boolean
Default: false

By default, the target is deeply cloned.
When true, it is directly mutated instead, which is faster but has side effects.

const target = {} console.log(set(target, 'name', 'Alice')) // { name: 'Alice' } console.log(target) // {} console.log(set(target, 'name', 'Alice', { mutate: true })) // { name: 'Alice' } console.log(target) // { name: 'Alice' } entries

Methods: get(), list(), iterate()
Type: boolean
Default: false

By default, properties' values are returned.
When true, objects with the following shape are returned instead:

value any: property's value path Path: property's full path missing boolean: whether the property is missing from the target

const target = { firstName: 'Alice', lastName: 'Smith' } list(target, '*') // ['Alice', 'Smith'] list(target, '*', { entries: true }) // [ // { value: 'Alice', path: ['firstName'], missing: false }, // { value: 'Smith', path: ['lastName'], missing: false }, // ] missing

Methods: all except has() and remove()
Type: boolean
Default: false with list|iterate(), true with set()

When false, properties not defined in the target are ignored.

const target = {} set(target, 'name', 'Alice') // { name: 'Alice' } set(target, 'name', 'Alice', { missing: false }) // {} list(target, 'name') // [] list(target, 'name', { missing: true, entries: true }) // [{ value: undefined, path: ['name'], missing: true }] sort

Methods: get(), list(), iterate()
Type: boolean
Default: false

When returning sibling object properties, sort them by the lexigographic order of their names (not values).

const target = { lastName: 'Doe', firstName: 'John' } list(target, '*') // ['Doe', 'John'] list(target, '*', { sort: true }) // ['John', 'Doe'] childFirst

Methods: get(), list(), iterate()
Type: boolean
Default: false

When using unions or deep wildcards, a query might match both a property and some of its children.

This option decides whether the returned properties should be sorted from children to parents, or the reverse.

const target = { user: { name: 'Alice' } } list(target, 'user.**') // [{ name: 'Alice' }, 'Alice'] list(target, 'user.**', { childFirst: true }) // ['Alice', { name: 'Alice' }] leaves

Methods: all except has()
Type: boolean
Default: false

When using unions or deep wildcards, a query might match both a property and some of its children.

When true, only leaves are matched. In other words, a matching property is ignored if one of its children also matches.

const target = { user: { name: 'Alice' } } list(target, 'user.**') // [{ name: 'Alice' }, 'Alice'] list(target, 'user.**', { leaves: true }) // ['Alice'] roots

Methods: get(), list(), iterate()
Type: boolean
Default: false

When using unions or deep wildcards, a query might match both a property and some of its children.

When true, only roots are matched. In other words, a matching property is ignored if one of its parents also matches.

const target = { user: { name: 'Alice' } } list(target, 'user.**') // [{ name: 'Alice' }, 'Alice'] list(target, 'user.**', { roots: true }) // [{ name: 'Alice' }] shallowArrays

Methods: all
Type: boolean
Default: false

If true, wildcards do not recurse on arrays. Array items can still be matched by using indices or slices.

const target = [{ name: 'Alice' }, { name: 'Bob' }] list(target, '**') // [ // [{ name: 'Alice' }, { name: 'Bob' }], // { name: 'Alice' }, // 'Alice', // { name: 'Bob' }, // 'Bob', // ] list(target, '**', { shallowArrays: true }) // [ // [{ name: 'Alice' }, { name: 'Bob' }], // ] classes

Methods: all
Type: boolean
Default: false

Unless true, wildcards and regexps ignore properties of objects that are not plain objects (like class instances, errors or functions). Those can still be matched by using their property name.

const target = { user: new User({ name: 'Alice' }) } list(target, 'user.*') // [] list(target, 'user.*', { classes: true }) // ['Alice'] inherited

Methods: all
Type: boolean
Default: false

By default, wildcards and regexps ignore properties that are either inherited or not enumerable. Those can still be matched by using their property name.

When true, inherited properties are not ignored, but not enumerable ones still are.

Related projects wild-wild-utils: functional utilities using wild-wild-path's object property paths wild-wild-parser: parser for wild-wild-path's object property paths Support

For any question, don't hesitate to submit an issue on GitHub.

Everyone is welcome regardless of personal background. We enforce a Code of conduct in order to promote a positive and inclusive environment.

Contributing

This project was made with . The simplest way to give back is by starring and sharing it online.

If the documentation is unclear or has a typo, please click on the page's Edit button (pencil icon) and suggest a correction.

If you would like to help us fix a bug or add a new feature, please check our guidelines. Pull requests are welcome!


ehmicky

Sylvain

版权声明:

1、该文章(资料)来源于互联网公开信息,我方只是对该内容做点评,所分享的下载地址为原作者公开地址。
2、网站不提供资料下载,如需下载请到原作者页面进行下载。