1
var data = {
  'id': 'object1',
  'sceneCapability': {
  'updatedAt': '2017-06-19T20:52:45.688Z'
    'currentScene': {
      'value': {
        'number': 1,
        'name': '1'
      }
    },
    'outOfTune': {
      'value': false
    }
  },

  'lightingCapability': {
    'intensity': {
      'value': 0
    }
  },

  'tiltCapability': {
    'command': {
      'value': 'NO'
    },
    'position': {
      'value': 0
    }
  }

// like this I have different types of more than 20 Capabilities 
};

How can I write a generic method to parse this Object? I need to get currentScene value, outOfTune, intensity, command, position, etc...

Sometimes I get only one capability and sometime I get more than 20 capabilities.

I want to avoid doing something like this because in future there might be hundreds of different capabilities

if (obj.lightingCapability && obj.lightingCapability.intensity) {
        console.log(obj.lightingCapability.intensity.value)
}

if (device.sceneCapability && device.sceneCapability.outOfTune) {
            // do something
        }

Output I want something like

currentScene:1,
outOfTune: false,
intensity: 0,
command: 'NO',
position: 0
2
  • Will your keys always end in the word "Capability"? Commented Jun 20, 2017 at 13:45
  • @kevin628 yes, they will end with Capability always. Commented Jun 20, 2017 at 13:54

5 Answers 5

4

Maybe something like this will work for you?

A helper function that finds the property you need and returns null if anything along the chain doesn't exist. I added two 'different' versions in case you don't like the array of property names.

var object = {
    a: {
        b: {
            c: {
                d: 10
            }
        }
    }
};

function getValue(object, propertyPath) {
    var o = object;
    var pLen = propertyPath.length;

    for (var i = 0; i < pLen; i++) {
        var propertyName = propertyPath[i];
        if (!o.hasOwnProperty(propertyName))
            return undefined;

        o = o[propertyName];
    }

    return o;
}

function getValueFromString(object, path) {
    return this.getValue(object, path.split('.'));
}

console.log(getValue(object, ['a', 'b', 'c', 'd']));    //logs 10
console.log(getValueFromString(object, 'a.b.c.d'));     //logs 10
console.log(getValue(object, ['a', 'b', 'c', 'e']));    //logs undefined
Sign up to request clarification or add additional context in comments.

8 Comments

Oh, it looks like you had the same idea and beat me to it. Is there really a benefit to including the wrapper that takes the keys as a string vs just splitting the keys in the getvalue method?
So we before calling this method I need to have the keyChain, isn't it? just wondering is there a way to achieve this without knowing the key chain?
@Marie Not at all. I added the getValueFromString method afterwards in an edit and wanted to keep it short for conciseness.
@PratapA.K Just the key, or the whole key chain up to there? Maybe just something like JSON.stringify(object) could be useful here?
@PratapA.K Check this answer, I think it will do what you want stackoverflow.com/questions/34513964/…
|
3

Based on the discussion we had in the comments of my first answer I realized you meant something different. This should do the trick:

var object = {
    a: {
        b: {
            c: {
                value: 10
            },
            d: {
                e: {
                    value: 20
                }
            }
        }
    }
};

function logAllValues(object) {
    for (var p in object) {
        var o = object[p];
        if (o.value)
            console.log(p + ': ' + o.value);
        else 
            logAllValues(o);
    }
}

logAllValues(object);    //logs c:10 and e:20

1 Comment

This would fail if the value was fasley, what about o.hasOwnProperty("value")?
1

A slightly hacky way to do this would be to create a helper function that allows the key chain to be passed in as a string and loop over it. For example

function getValue(obj, keyChain){
  var keys = keyChain.split('.');
  do {
    var key = keys.shift();
    if (!obj.hasOwnProperty(key)){
      return undefined;
    }
    obj = obj[key];
  } while (keys.length > 0);
  return obj;
}

getValue(data, "lightingCapability.intensity.value")

3 Comments

So we before calling this method I need to have the keyChain, isn't it? just wondering is there a way to achieve this without knowing the key chain?
Sorry, I am not sure I follow. You want to access a specific value without knowing where the value is?
yea, it looks bit weird because each capabilities has different parameters.
0

I think you just need to install lodash#get

npm i --save lodash.get

var get = require('lodash.get');

if(get('foo.baz.foobaz')) {
  alert('yep');
}

but you always will need to know all the paths you need in advance.

Re-implementing this well community tested method will end up in re-inventing the wheel, so, just install and use it.

Comments

-1

you can implement some thing like this using ES6 try and catch block

var object = {
    a: {
        b: {
            c: {
                value: 10
            },
            d: {
                e: {
                    value: 20
                }
            }
        }
    }
};

function getValue(jsObject) {
    try {
        return jsObject();
    } catch (e) {
        return undefined;
    }
}

// use it like this

getValue(() => object.a.b); // returns Object {c: Object, d: Object}

getValue(() => object.a.b.c); // returns Object {value: 10}

getValue(() => object.a.b.x); // returns undefined

2 Comments

You really shouldnt use a try-catch to control the flow of logic like that.
Generally yes. The code is definitely cleaner but negative cases will get a serious performance hit. When possible you should use other logic to avoid the need for a try-catch block.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.