如何检查对象结构是否存在?

时间:2014-07-24 03:05:49

标签: javascript json javascript-objects

假设我从第三方来源解析JSON对象:

var myObject = {
  person_list: [
    { black_hair: {
      list: [
        'bob',
        'john',
        'allen'
      ]}
    }
  ]
};

但是如果结构突然改变或者数据响应可能已损坏,我该如何检查结构的深度部分是否存在?

我能做到

if ( myObject.person_list.black_hair.list !== undefined ) {
  // do stuff
}

但在某些情况下,black_hair可能不存在。如果它从对象中丢失,那么我得到Uncaught TypeError: Cannot read property 'list' of undefined。因此,我能想到检查整个结构是否完整的唯一方法是检查每个级别是否已定义:

if ( myObject.person_list !== undefined ) {
  if ( myObject.person_list.black_hair !== undefined ) {
    if ( myObject.person_list.black_hair.list !== undefined ) {
      // do stuff
    }
  }
}

但这有点荒谬。有一种简单的方法可以在JavaScript中处理这个问题吗?是尝试,抓住最好的方法吗?

3 个答案:

答案 0 :(得分:2)

您可以定义一个函数来检查完整结构:

function defined_structure(obj, attrs) {

    var tmp = obj;

    for(i=0; i<attrs.length; ++i) {
        if(tmp[attrs[i]] == undefined)
            return false;
        tmp = tmp[attrs[i]];
    }

    return true;
}

//...

if(defined_structure(myObject, ['person_list', 0, 'black_hair', 'list']) {
    // Do stuff
}

第一个参数是具有要检查结构的对象,第二个参数是具有嵌套属性名称的数组。

<强>更新

正如@chiliNUT所指出的,person_list是一个数组。无论如何,这种方法的工作原理是添加您要检查的项目的索引(即['person_list', 0, 'black_hair', 'list'])。

答案 1 :(得分:0)

您可以使用我写的这个函数来检查属性是否已设置。您只需要将该路径作为字符串传递给该属性。

// Check if nested object properties exist on unlimited levels
// param: str 'obj.property.property'
function isset (property)
{
    // split path to object property
    var properties = property.split('.');
    var obj = this;

    //loop through each portion of the path checking if it exists
    for (var i = 0; i < properties.length; i++)
    {
        var current_property = properties[i];
        var next_property = i < properties.length - 1 ? true : false;

        // IF current property exists then we need to check the next level
        if (obj[current_property] !== null && typeof obj[current_property] === 'object' && next_property)
        {
            obj = obj[current_property];
            continue;
        }
        return obj.hasOwnProperty(current_property);
    }
}

if ( isset('myObject.person_list.black_hair.list')) {
    // do stuff
}

答案 2 :(得分:0)

使用 meta 对象更好地映射预期格式

var meta = {
    name: "person_list",
    type: [],
    component: [{
        name: 'black_hair',
        type: {},
        component: {
            name: 'list',
            type: []
        }
    }]
};

var myObject = {
    person_list: [{
        asdfa: {
            list: [
                'bob',
                'john',
                'allen']
        }
    }]
};

function defined(meta, obj) {
    if (meta.name == 'list' && obj[meta.name] && obj[meta.name].length) {
        return true;
    }
    if (!obj[meta.name]) {
        return false;
    };
    if (Object.prototype.toString.call(meta.type) === '[object Array]' && !obj[meta.name].length) {
        return false;
    } else if (Object.prototype.toString.call(meta.type) === '[object Array]' && obj[meta.name].length) {
        for (index in obj[meta.name]) {
            return defined(meta.component[index], obj[meta.name][index]);
        }
    } else if (Object.prototype.toString.call(meta.type) === '[object Object]') {
        return defined(meta.component, obj[meta.name]);
    }
}

console.log(defined(meta, myObject));

DEMO