2013-09-05 3 views
2

Часто в ответ от удаленного вызова API, я получаю вложенные объекты:Nicer способ получить вложенные атрибуты объекта

var response = { 
    data : { 
     users : [ 
      { 
       name : 'Mr. White' 
      } 
     ] 
    } 
} 

Я хочу, чтобы проверить, является ли имя первого пользователя «Mr. Белый », и, естественно, хотел бы написать что-то вроде этого.

var existed = response.data.users[0].name === 'Mr. White' 

Однако я не могу быть уверен, что, если все объекты присутствуют, поэтому, чтобы избежать исключения вместо этого я в конечном итоге написание:

var existed = response && response.data && response.data.users && response.data.users[0].name === 'Mr. White' 

Есть ли лучше способ сделать это? Еще один уродливый вариант, который приходит на ум:

var existed = false; 
try { 
    var existed = response.data.users[0].name === 'Mr. White'; 
} catch(e) { } 

В дополнение к ванили JavaScript, я обычно underscore.js и JQuery доступны также.

Edit:

К сожалению, заметил, что я задал контратип javascript test for existence of nested object key.

Интересный вариант на основе этих ответов:

var existed = (((response || {}).data || {}).users || [{}])[0].name === 'Mr. White'; 
+3

'try/catch' является самым чистым решением IMO. –

+1

Вы можете рассмотреть библиотеку [dotty.js] (https://github.com/deoxxa/dotty). Это небольшая специализированная библиотека для извлечения вещей из вложенных объектов. – Paul

+0

Dotty выглядит интересно, но если бы я читал код, я думаю, что это смущает меня больше, чтобы увидеть библиотеку, используемую для такой небольшой цели. – Bemmu

ответ

1

Вы можете скрыть этот озорной блок Try/поймать внутри функции, как этот:

function resolve(root, path){ 
    try { 
     return (new Function(
      'root', 'return root.' + path + ';' 
     ))(root); 
    } catch (e) {} 
} 

var tree = { level1: [{ key: 'value' }] }; 
resolve(tree, 'level1[0].key'); // "value" 
resolve(tree, 'level1[1].key'); // undefined 

Подробнее об этом: https://stackoverflow.com/a/18381564/1636522

+0

Отметьте это как правильное, так как оно содержит некоторые новые трюки, о которых я не знал. – Bemmu

+0

Один трюк вдохновлен jQuery, который анализирует строки JSON, используя 'new Function'. Обратите внимание, что вы можете настроить формат пути, заменяющий косую черту в 'path.split ('/')' любым выбранным вами символом. – leaf

1

Я хотел бы использовать крылатую подход попробовать, но обернуть его в функции, чтобы скрыть уродство.

1

Вместо try/catch, это должно быть сделано с помощью проверки, является ли каждый уровень в объекте определено или нет.

пойти

if(typeof(response)!="undefined" 
    && typeof(response.data)!="undefined" 
    && typeof(response.data.users)!="undefined" 
    && typeof(response.data.users[0])!="undefined" 
    && typeof(response.data.users[0].name)!="undefined" 
) { 

    //executes only if response.data.users[0].name is existing 

} 
1

Вот функция, которую я использовал в одном из моих проектов http://jsfiddle.net/JBBAJ/

var object = { 
    data: { 
     users: [ 
      { 
       firstName: "White" 
      }, 
      { 
       firstName: "Black" 
      } 
     ] 
    } 
} 
var read = function(path, obj) { 
    var path = path.split("."); 
    var item = path.shift(); 
    if(item.indexOf("]") == item.length-1) { 
     // array 
     item = item.split("["); 
     var arrayName = item.shift(); 
     var arrayIndex = parseInt(item.shift().replace("]", "")); 
     var arr = obj[arrayName || ""]; 
     if(arr && arr[arrayIndex]) { 
      return read(path.join("."), arr[arrayIndex]); 
     } else { 
      return null; 
     } 
    } else { 
     // object 
     if(obj[item]) { 
      if(path.length === 0) { 
       return obj[item]; 
      } else { 
       return read(path.join("."), obj[item]); 
      } 
     } else { 
      return null; 
     } 
    } 

} 
console.log(read("data.users[0].firstName", object)); // White 
console.log(read("data.users[1].firstName", object)); // Black 
console.log(read("data.test.users[0]", object)); // null 

Идея заключается в том, чтобы пройти свой путь в виде строки вместе с объектом. Идея состояла в том, чтобы предотвратить выброс исключения и получить только нуль, поскольку результат пути неверен. Хорошо, что функция работает с каждым путем, и вам не нужно писать длинные операторы if.

Смежные вопросы