How do I verify if several attributes are in a JSON structure within JavaScript?

I am creating a module that takes in several complicated JSON files and would like some code to give the user feedback if certain elements are absent.

Below is the way I am doing it now, but I cannot help to think there must be a cleaner, less hacky way.

var _und = require("underscore");
//this function takes a list of required attributes and ensures they are present
var check_req_attr = function(config, req_attr, callback) {
    var config_attr = Object.keys(config);
    var absent_attr = _und.difference(req_attr, config_attr); //slightly hacky code that checks to ensure config has correct vars
    if (absent_attr.length !== 0) {
        throw Error("missing following attributes from config:" + absent_attr);
    } else {
        callback();
    };
};

It just feels...dirty. If there is no real elegant way to do it, I would be open to critiques on my code. Thanks!

  1. Parse the JSON to JS.

    var data = JSON.parse(theJson);

  2. Use something like:

    function hasKey(obj, key) {
        return typeof obj[key] !== 'undefined';
    };
    
    
    
    function hasKeys(obj, keys) {
    
        for (var i = 1, len = keys.length; i < len; i++) {
            if (!hasKey(obj, keys[i])) {
                return false;
            };
        };
        return true;
    };
    

Now you can simply do:

if (hasKeys(data, ["firstKey", "secondKey", "thirdKey"]) {
    console.log("valid");
};

This should be the way to do it, using every and has:

if (_und.every(req_attr, function(attr) {
    return _und.has(config, attr);
}))
    throw new Error();

In a native environment, you would just use the in operator:

req_attr.every(function(attr){ return attr in config; })

I think your solution is actually quite elegant! No need for an anonymous function, and the loop (which must happen at some point, obviously) neatly abstracted away with difference.

Two suggestions:

  1. I'd give the function a synchronous signature. No callback argument. There can't be any reason to go async if you honor the function signature (i.e. basing your answer on config and req_attr only).

  2. I'd change the function to return the missing properties (attributes is wrong term). You could also add a requireProperties function that uses this "check" function that would throw if a property was missing. This allows for different kind of uses.

Why don't you try with something like:

obj = JSON.parse(json);

and then check

if(obj.YourProperty == undefined){
    //do something..
}

Hope i understood your question.. It should work with complicated JSON files too.. Good luck ;)

You could also use the in operator (requiredAttr in obj):

function objHasAllRequiredAttrs(obj, attrNames) {
  return attrNames.reduce(function(memo, attrName) {
    return memo && (attrName in obj);
  }, true);
}

objHasAllRequiredAttrs({foo:1}, ['foo']); // => true
objHasAllRequiredAttrs({bar:1}, ['foo']); // => false