DEV Community

Jitesh Dhamaniya
Jitesh Dhamaniya

Posted on

2 2

Get Nested Property from a Object in JS

Recently Stumbled upon this nice snippet for accessing Nested property using String.

/**
 * get property of object
 * @param obj object
 * @param path e.g user.name
 */
function getProperty(obj, path, defaultValue = '-') {
    const value = path.split('.').reduce((o, p) => o && o[p], obj);

    return value ? value : defaultValue;
  }
Enter fullscreen mode Exit fullscreen mode

and this how you use it

getProperty(object, 'passengerDetails.data.driverInfo.currentVehicle.vehicleType')
Enter fullscreen mode Exit fullscreen mode

Reference
https://stackoverflow.com/a/64239231/11164153

Would be interested to learn if there is any other easier or better way.

Top comments (1)

Collapse
 
tominoff profile image
Tominov Sergey • Edited

I think you should never use naive boolean conversion for such things because JS has at least 6 falsy types which can be used as regular values. This function you showed, gives you false positive result when you try extract that kind of values:

const obj = { 
  a: { 
    b1: false, 
    b2: null, 
    b3: undefined, 
    b4: NaN, 
    b5: 0, 
    b6: ''
  } 
}

getProperty(obj, 'a.b1') // '-'
getProperty(obj, 'a.b2') // '-'
getProperty(obj, 'a.b3') // '-'
getProperty(obj, 'a.b4') // '-'
getProperty(obj, 'a.b5') // '-'
getProperty(obj, 'a.b6') // '-'
Enter fullscreen mode Exit fullscreen mode

Instead of naive boolean conversions to check if object property exists always use .hasOwnProperty.👍 As a possible solution for your needs (return some defaults if path is incorrect) you can use symbols:

const NOT_FOUND_SYMBOL = Symbol('function:getProperty:notFound')

function getProperty (obj, path, defaultValue = '', pathDelimiter = '.') {
  const pathValue = path
    .split(pathDelimiter)
    .reduce((prev, curr) => {
      // when not found we don't need to go deeper, kind of early exit
      return (prev !== NOT_FOUND_SYMBOL && prev.hasOwnProperty(curr)) 
        ? prev[curr] 
        : NOT_FOUND_SYMBOL
    }, obj)

  return pathValue !== NOT_FOUND_SYMBOL ? pathValue : defaultValue
}

const obj = {
  a: { b: { 
    c1: null,
    c2: false,
    c3: NaN,
    c4: '',
    c5: 0,
    c6: undefined,
    c7: `It's ok`
  }}
}

console.log(getProperty(obj, 'a.b.c0', 'Path is incorrect')) // 'Path is incorrect'
console.log(getProperty(obj, 'a.b.c1', 'Path is incorrect')) // null
console.log(getProperty(obj, 'a.b.c2', 'Path is incorrect')) // false
console.log(getProperty(obj, 'a.b.c3', 'Path is incorrect')) // NaN
console.log(getProperty(obj, 'a.b.c4', 'Path is incorrect')) // ''
console.log(getProperty(obj, 'a.b.c5', 'Path is incorrect')) // 0
console.log(getProperty(obj, 'a.b.c6', 'Path is incorrect')) // undefined
console.log(getProperty(obj, 'a.b.c7', 'Path is incorrect')) // "It's ok"
Enter fullscreen mode Exit fullscreen mode

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay