A tiny JavaScript utility to access deep properties using a path (for Node and the Browser)

Overview

object-path

Access deep properties using a path

NPM version Build Status Coverage Status devDependency Status Downloads

Changelog

0.11.5

  • SECURITY FIX. Fix a prototype pollution vulnerability in the set() function when using the "inherited props" mode (e.g. when a new object-path instance is created with the includeInheritedProps option set to true or when using the withInheritedProps default instance. The vulnerability does not exist in the default instance exposed by object path (e.g objectPath.set()) if using version >= 0.11.0.

0.11.0

  • Introduce ability to specify options and create new instances of object-path
  • Introduce option to control the way object-path deals with inherited properties (includeInheritedProps)
  • New default object-path instance already configured to handle not-own object properties (withInheritedProps)

0.10.0

  • Improved performance of get, set, and push by 2x-3x
  • Introduced a benchmarking test suite
  • BREAKING CHANGE: del, empty, set will not affect not-own object's properties (made them consistent with the other methods)

Install

Node.js

npm install object-path --save

Bower

bower install object-path --save

Typescript typings

typings install --save dt~object-path

Usage

var obj = {
  a: {
    b: "d",
    c: ["e", "f"],
    '\u1200': 'unicode key',
    'dot.dot': 'key'
  }
};

var objectPath = require("object-path");

//get deep property
objectPath.get(obj, "a.b");  //returns "d"
objectPath.get(obj, ["a", "dot.dot"]);  //returns "key"
objectPath.get(obj, 'a.\u1200');  //returns "unicode key"

//get the first non-undefined value
objectPath.coalesce(obj, ['a.z', 'a.d', ['a','b']], 'default');

//empty a given path (but do not delete it) depending on their type,so it retains reference to objects and arrays.
//functions that are not inherited from prototype are set to null.
//object instances are considered objects and just own property names are deleted
objectPath.empty(obj, 'a.b'); // obj.a.b is now ''
objectPath.empty(obj, 'a.c'); // obj.a.c is now []
objectPath.empty(obj, 'a'); // obj.a is now {}

//works also with arrays
objectPath.get(obj, "a.c.1");  //returns "f"
objectPath.get(obj, ["a","c","1"]);  //returns "f"

//can return a default value with get
objectPath.get(obj, ["a.c.b"], "DEFAULT");  //returns "DEFAULT", since a.c.b path doesn't exists, if omitted, returns undefined

//set
objectPath.set(obj, "a.h", "m"); // or objectPath.set(obj, ["a","h"], "m");
objectPath.get(obj, "a.h");  //returns "m"

//set will create intermediate object/arrays
objectPath.set(obj, "a.j.0.f", "m");

//will insert values in array
objectPath.insert(obj, "a.c", "m", 1); // obj.a.c = ["e", "m", "f"]

//push into arrays (and create intermediate objects/arrays)
objectPath.push(obj, "a.k", "o");

//ensure a path exists (if it doesn't, set the default value you provide)
objectPath.ensureExists(obj, "a.k.1", "DEFAULT");
var oldVal = objectPath.ensureExists(obj, "a.b", "DEFAULT"); // oldval === "d"

//deletes a path
objectPath.del(obj, "a.b"); // obj.a.b is now undefined
objectPath.del(obj, ["a","c",0]); // obj.a.c is now ['f']

//tests path existence
objectPath.has(obj, "a.b"); // true
objectPath.has(obj, ["a","d"]); // false

//bind object
var model = objectPath({
  a: {
    b: "d",
    c: ["e", "f"]
  }
});

//now any method from above is supported directly w/o passing an object
model.get("a.b");  //returns "d"
model.get(["a.c.b"], "DEFAULT");  //returns "DEFAULT"
model.del("a.b"); // obj.a.b is now undefined
model.has("a.b"); // false

How object-path deals with inherited properties

By default object-path will only access an object's own properties. Look at the following example:

var proto = {
  notOwn: {prop: 'a'}
}
var obj = Object.create(proto);

//This will return undefined (or the default value you specified), because notOwn is
//an inherited property
objectPath.get(obj, 'notOwn.prop');

//This will set the property on the obj instance and not the prototype.
//In other words proto.notOwn.prop === 'a' and obj.notOwn.prop === 'b'
objectPath.set(obj, 'notOwn.prop', 'b');

To configure object-path to also deal with inherited properties, you need to create a new instance and specify the includeInheritedProps = true in the options object:

var objectPath = require("object-path");
var objectPathWithInheritedProps = objectPath.create({includeInheritedProps: true})

Alternatively, object-path exposes an instance already configured to handle inherited properties (objectPath.withInheritedProps):

var objectPath = require("object-path");
var objectPathWithInheritedProps = objectPath.withInheritedProps

Once you have the new instance, you can access inherited properties as you access other properties:

var proto = {
  notOwn: {prop: 'a'}
}
var obj = Object.create(proto);

//This will return 'a'
objectPath.withInheritedProps.get(obj, 'notOwn.prop');

//This will set proto.notOwn.prop to 'b'
objectPath.set(obj, 'notOwn.prop', 'b');

Immutability

If you are looking for an immutable alternative of this library, you can take a look at: object-path-immutable

Credits

Comments
  • Array indices in .set

    Array indices in .set

    Hello! Thanks for the great module!

    I'm confused with the behaviour of the .set method. I expect that when I do something like this:

    objectPath.set(obj, "a.0.b", "value")
    

    I will get the following structure:

    { a: [ { b: "value" } ] }
    

    Instead I'm getting:

    { a: { '0': [ b: 'value' ] } }
    

    I believe that's incorrect, because it is setting named properties of arrays treating array indices as object keys at the same time. If this is an intended behaviour, then, what path should I pass to .set to get the structure like in the first example? Probably, there should be a special syntax for array indices, e.g.:

    objectPath.set(obj, "a[0].b", "value")
    

    I can submit a patch for this (probably, next week), if it's OK to add this functionality.

    Thank you!

    opened by vne 16
  • get(global, 'navigator.userAgent') === undefined

    get(global, 'navigator.userAgent') === undefined

    ObjectPath.get(global, 'navigator.userAgent') // undefined
    
    const Navigator = ObjectPath.get(global, 'navigator') // Navigator
    ObjectPath.get(Navigator, 'userAgent') // undefined
    
    navigator.userAgent // Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 ...
    navigator['userAgent'] // Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 ...
    
    opened by kilianc 8
  • Method set in simple paths

    Method set in simple paths

    When it is passed a simple path to set method I expect to have the same behaviour of expression:

    obj[path] = value
    

    Examples:

    var obj = {}
    objectPath.set(obj, 3, 'foo') // now obj is {3: 'foo'}
    // or
    var obj = {}
    obj[3] = 'foo'
    
    var obj = {}
    objectPath.set(obj, 'a', 'foo') // now obj is {a: 'foo'}
    // or
    var obj = {}
    obj['a'] = 'foo' // now obj is {a: 'foo'}
    

    But exist in set method one case that it behaves different:

    var obj = {}
    objectPath.set(obj, '', 'foo') // now obj is {}
    // however
    var obj = {}
    obj[''] = 'foo' // now obj is {'': 'foo'}
    

    I think that it would be a good idea change behaviour in this case to keep the consistency. I think the same for another methods.

    opened by xgbuils 6
  • Accessing non-enumerable properties with object-path

    Accessing non-enumerable properties with object-path

    Hey Mario,

    The following test case yielded unexpected results for me:

    var path = require("object-path")
    
    var obj = {
      arr: [],
      b: {
        a: [],
        c: {}
      }
    };
    
    console.log(path.get(obj, 'arr'))             // []
    console.log(path.get(obj, 'arr.length'))      // undefined
    console.log(path.get(obj, 'b'))               // { a:[], c: {} }
    

    I believe it's down to accessing non-enumerable properties using object-path. I've included a failing test case in the PR. Just highlighting it in case anyone else runs into the issue!

    opened by johnbrett 6
  • `del` method behaves differently on arrays than `delete` operator

    `del` method behaves differently on arrays than `delete` operator

    The delete operator does not splice from or otherwise modify the length of arrays. It removes that key, but the other elements retain their index.

    object-path's del method instead uses splice (index.js#L124), which modifies the length of the array and changes the index of all elements after the deleted element.

    For my use case, I would like to use the normal delete operator behavior. This would be a breaking change though, so I'm unsure what the best way of approaching this change would be.

    Source: MDN Article on the delete operator

    opened by alvancamp 5
  • (intermediate value)(...) is not a function error in code immediately following index.js from object-path

    (intermediate value)(...) is not a function error in code immediately following index.js from object-path

    image Since upgrading object-path to 0.11.8 this error started appearing. I think it's because of the removed ; in index.js on https://github.com/mariocasciaro/object-path/commit/4f0903fd7c832d12ccbe0d9c3d7e25d985e9e884#diff-e727e4bdf3657fd1d798edcd6b099d6e092f8573cba266154583a746bba0f346L306 image I am only using index.js in my project, could be an issue in other files as well.

    opened by ghost 4
  • Question/Enhancement: Return nested values from array

    Question/Enhancement: Return nested values from array

    Suppose I have a object like this:

    const obj = { tags: [ {name: 'one'}, {name: 'two'}, {name: 'three'}, ] }

    I read from the API that you can get a single value of a known index: ObjectPath.get(obj,'tags.1.name') // returns 'two'

    But does object-path allow for a path that can map the nested 'name' value?

    e.g. ObjectPath.get(obj,'tags.*.name') // returns ['one','two','three']

    Thanks

    opened by ZephD 4
  • get a null path not return the defaultValue

    get a null path not return the defaultValue

    See https://runkit.com/586945e631af31001472d7f4/5871ebc5fe814b0013db83e5

    Current behavior:

    return the whole object.

    Expected behavior:

    return the defaultValue.

    Related code: https://github.com/mariocasciaro/object-path/blob/2b80d6cf4e0939e59e525cc1f65da18ad8767beb/index.js#L224-L229

    opened by yesmeck 4
  • has doesn't work with sparse arrays

    has doesn't work with sparse arrays

    Hey, I've noticed that has throws an error when I try to check a nested path in a sparse array. I believe it should return false in this case.

    Example: objectPath.has({ foo: [undefined, undefined, undefined] }, 'foo.0.bar')

    Throws:

     Uncaught TypeError: Cannot convert undefined or null to object(…)
     objectPath.has @ index.js:136
    
    bug 
    opened by mxdubois 4
  • Should it throw an error if the property is not defined and defaultValue is missing?

    Should it throw an error if the property is not defined and defaultValue is missing?

    expect(objectPath.get({}, 'deep.notDefined', undefined)).to.equal(undefined);
    

    but

    try {
      objectPath.get({}, 'deep.notDefined');
    } catch (e) {
      assert(e.toString() === 'TypeError: Cannot read property \'notDefined\' of undefined');
    }
    
    opened by stevemao 4
  • Typescript definitions

    Typescript definitions

    I've created borisyankov/DefinitelyTyped#2584 (although I didn't finish the #18 issue yet). It's nice to have this on the readme when they accept the PR :)

    opened by pocesar 4
  • Bump qs from 6.5.2 to 6.5.3

    Bump qs from 6.5.2 to 6.5.3

    Bumps qs from 6.5.2 to 6.5.3.

    Changelog

    Sourced from qs's changelog.

    6.5.3

    • [Fix] parse: ignore __proto__ keys (#428)
    • [Fix] utils.merge: avoid a crash with a null target and a truthy non-array source
    • [Fix] correctly parse nested arrays
    • [Fix] stringify: fix a crash with strictNullHandling and a custom filter/serializeDate (#279)
    • [Fix] utils: merge: fix crash when source is a truthy primitive & no options are provided
    • [Fix] when parseArrays is false, properly handle keys ending in []
    • [Fix] fix for an impossible situation: when the formatter is called with a non-string value
    • [Fix] utils.merge: avoid a crash with a null target and an array source
    • [Refactor] utils: reduce observable [[Get]]s
    • [Refactor] use cached Array.isArray
    • [Refactor] stringify: Avoid arr = arr.concat(...), push to the existing instance (#269)
    • [Refactor] parse: only need to reassign the var once
    • [Robustness] stringify: avoid relying on a global undefined (#427)
    • [readme] remove travis badge; add github actions/codecov badges; update URLs
    • [Docs] Clean up license text so it’s properly detected as BSD-3-Clause
    • [Docs] Clarify the need for "arrayLimit" option
    • [meta] fix README.md (#399)
    • [meta] add FUNDING.yml
    • [actions] backport actions from main
    • [Tests] always use String(x) over x.toString()
    • [Tests] remove nonexistent tape option
    • [Dev Deps] backport from main
    Commits
    • 298bfa5 v6.5.3
    • ed0f5dc [Fix] parse: ignore __proto__ keys (#428)
    • 691e739 [Robustness] stringify: avoid relying on a global undefined (#427)
    • 1072d57 [readme] remove travis badge; add github actions/codecov badges; update URLs
    • 12ac1c4 [meta] fix README.md (#399)
    • 0338716 [actions] backport actions from main
    • 5639c20 Clean up license text so it’s properly detected as BSD-3-Clause
    • 51b8a0b add FUNDING.yml
    • 45f6759 [Fix] fix for an impossible situation: when the formatter is called with a no...
    • f814a7f [Dev Deps] backport from main
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • [Suggestion] Deep merge like in object-path-immutable?

    [Suggestion] Deep merge like in object-path-immutable?

    Since this library is a dependency of your immutable version, I think it would make sense to move functions like merge/assign/update to this library so they can both have similar functionality, except immutability.

    I'd like to have the option to either overwrite(set) or merge, which seems possible with the immutable version. I cant use the immutable version of this library however, as I want to update the original object for performance instead of cloning it.

    opened by jrj2211 0
  • Bump minimatch from 3.0.4 to 3.1.2

    Bump minimatch from 3.0.4 to 3.1.2

    Bumps minimatch from 3.0.4 to 3.1.2.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Bump minimist from 1.2.5 to 1.2.6

    Bump minimist from 1.2.5 to 1.2.6

    Bumps minimist from 1.2.5 to 1.2.6.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Transform properties

    Transform properties

    Dear, Thanks for sharing this useful library!

    I was wondering if it is somehow possible to transform object properties (from original value into a new value).

    Something like this:

    objectPath.set(obj, "a.j.0.f", function(originalValue) {
       var newValue = originalValue + 2;
       return newValue;
    });
    

    Kind regards, Bart

    opened by bartbutenaers 0
Owner
Mario Casciaro
Maker • frontendrobot.com • Author of Node.js Design Patterns (https://nodejsdp.link/buy)
Mario Casciaro
HashMap JavaScript class for Node.js and the browser. The keys can be anything and won't be stringified

HashMap Class for JavaScript Installation Using npm: $ npm install hashmap Using bower: $ bower install hashmap You can download the last stable ver

Ariel Flesler 381 Sep 24, 2022
Immutable persistent data collections for Javascript which increase efficiency and simplicity.

Immutable collections for JavaScript Immutable data cannot be changed once created, leading to much simpler application development, no defensive copy

Immutable.js 32.4k Dec 31, 2022
ClojureScript's persistent data structures and supporting API from the comfort of vanilla JavaScript

mori A simple bridge to ClojureScript's persistent data structures and supporting APIs for vanilla JavaScript. Pull requests welcome. Breaking changes

David Nolen 3.4k Dec 31, 2022
A complete, fully tested and documented data structure library written in pure JavaScript.

Buckets A JavaScript Data Structure Library Buckets is a complete, fully tested and documented data structure library written in pure JavaScript. Incl

Mauricio 1.2k Jan 4, 2023
Immutable persistent data collections for Javascript which increase efficiency and simplicity.

Immutable collections for JavaScript Immutable data cannot be changed once created, leading to much simpler application development, no defensive copy

Immutable.js 32.4k Jan 7, 2023
Hjson for JavaScript

hjson-js Hjson, a user interface for JSON JSON is easy for humans to read and write... in theory. In practice JSON gives us plenty of opportunities to

Hjson 387 Dec 20, 2022
⚡️The Fullstack React Framework — built on Next.js

The Fullstack React Framework "Zero-API" Data Layer — Built on Next.js — Inspired by Ruby on Rails Read the Documentation “Zero-API” data layer lets y

⚡️Blitz 12.5k Jan 4, 2023
A tiny (304B to 489B) utility to check for deep equality

dequal A tiny (304B to 489B) utility to check for deep equality This module supports comparison of all types, including Function, RegExp, Date, Set, M

Luke Edwards 1.1k Dec 14, 2022
Grupprojekt för kurserna 'Javascript med Ramverk' och 'Agil Utveckling'

JavaScript-med-Ramverk-Laboration-3 Grupprojektet för kurserna Javascript med Ramverk och Agil Utveckling. Utvecklingsguide För information om hur utv

Svante Jonsson IT-Högskolan 3 May 18, 2022
An isomorphic and configurable javascript utility for objects deep cloning that supports circular references.

omniclone An isomorphic and configurable javascript function for object deep cloning. omniclone(source [, config, [, visitor]]); Example: const obj =

Andrea Simone Costa 184 May 5, 2022
Hemsida för personer i Sverige som kan och vill erbjuda boende till människor på flykt

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

null 4 May 3, 2022
Kurs-repo för kursen Webbserver och Databaser

Webbserver och databaser This repository is meant for CME students to access exercises and codealongs that happen throughout the course. I hope you wi

null 14 Jan 3, 2023
🧩 TypeScript utility type in order to ensure to return only properties (not methods) containing values in primitive types such as number or boolean (not Value Objects)

?? TypeScript Primitives type TypeScript utility type in order to ensure to return only properties (not methods) containing values in primitive types

CodelyTV 82 Dec 7, 2022
A tiny JavaScript debugging utility modelled after Node.js core's debugging technique. Works in Node.js and web browsers

debug A tiny JavaScript debugging utility modelled after Node.js core's debugging technique. Works in Node.js and web browsers. Installation $ npm ins

Sloth 10.5k Dec 30, 2022
Deep Learning in Javascript. Train Convolutional Neural Networks (or ordinary ones) in your browser.

ConvNetJS ConvNetJS is a Javascript implementation of Neural networks, together with nice browser-based demos. It currently supports: Common Neural Ne

Andrej 10.4k Dec 31, 2022
Userland module that implements the module path mapping that Node.js does with "exports" in package.json

exports-map Userland module that implements the module path mapping that Node.js does with "exports" in package.json npm install exports-map Usage co

Mathias Buus 9 May 31, 2022
a cobbled together alternative UI to launchdarkly, allowing read/write access via LD API access token

discount-launchdarkly a cobbled together alternative UI to launchdarkly, allowing read/write access via LD API access token setup make sure you have a

null 9 Oct 19, 2022
Node.js object hash library with properties/arrays sorting to provide constant hashes. It also provides a method that returns sorted object strings that can be used for object comparison without hashes.

node-object-hash Tiny and fast node.js object hash library with properties/arrays sorting to provide constant hashes. It also provides a method that r

Alexander 73 Oct 7, 2022
Animation Academy teaches you CSS animations using the transition and animation properties.

Animation Academy Open Animation Academy > Contents Background Built With Functionality Feature Highlights Wireframes Features In Development Backgrou

Jacob Benowitz 6 Jun 23, 2022