В javascript проверить свойство, глубоко вложенное в граф объектов? - PullRequest
4 голосов
/ 03 декабря 2010

У меня есть коллекция разрозненных, сложных объектов JSON из базы данных CouchDB. Каждый содержит много уровней вложенных свойств - например,

tps_report.personnel_info.productivity.units_sold = 8  

Я хочу перебрать эти объекты и поработать с ними: например,

// writes units sold from each TPS report:
for (i in tpsReports) {
  if (tpsReports[i].personnel_info.productivity.units_sold < 10) {
    fireEmployee();
  }
}

Проблема в том, что во многих отчетах TPS не установлены все эти свойства. Поэтому, если я попробую это сделать, я получу сообщение об ошибке, когда в первый раз цикл попадет в отчет без свойстваperson_info и, таким образом, попытается найти свойство производительности «undefined». Я бы предпочел, чтобы условное условие просто пропустило его и продолжило.

Я вижу два пути решения этой проблемы, которые кажутся мне безобразными

  1. проверка для каждого свойства отдельно с вложенными условными выражениями
  2. заключить строку в блок try / catch, чтобы перехватить ошибку и проигнорировать ее

Что бы я предпочел, это было бы что-то вроде PHP-функции isset (), которая не будет выдавать ошибку независимо от того, что вы ее кормите - она ​​просто скажет вам, существует ли конкретная переменная, которую вы ищете не. Итак, вроде

// writes units sold from each TPS report:
for (i in tpsReports) {
  if (isset(tpsReports[i].personnel_info.productivity.units_sold)){
    if (tpsReports[i].personnel_info.productivity.units_sold < 10) {
      fireEmployee();
    }
  }
}

Есть мысли?

Ответы [ 6 ]

5 голосов
/ 03 декабря 2010
function isset(obj, propStr) {
    var parts = propStr.split(".");
    var cur = obj;
    for (var i=0; i<parts.length; i++) {
        if (!cur[parts[i]])
            return false;
        cur = cur[parts[i]];
    }
    return true;
}

Обратите внимание, что вторым параметром является строка, поэтому исключение не генерируется при доступе к свойству несуществующего свойства.

2 голосов
/ 20 августа 2013
/**
 * units sold from each TPS report
 */

var units;

// the hard way
units = (report && report.personnel && report.personnel.info &&
        report.personnel.info.sales && report.personnel.info.sales.units &&
        report.personnel.info.sales.units.sold) || 0;

// the easy way
units = selectn('personnel.info.sales.units.sold', report) || 0;

// resulting action
if (units < 10) fireEmployee();

Бесстыдная вилка: я автор selectn .Доступно через npm install selectn или bower install selectn или component install wilmoore/selectn.

Посмотрите примеры в файле readme, чтобы узнать, почему это лучше, чем клон isset.Вы также можете использовать его как предикат filter , чтобы вы могли удалять вложенные объекты, которые не содержат определенного глубоко вложенного свойства.

2 голосов
/ 12 апреля 2013

Theres функция, определенная в этом блоге для безопасного чтения вложенных свойств из объекта JS

. Она позволяет вам добывать объект для свойств ... то есть.

safeRead(tps_report, 'personnel_info', 'productivity', 'units_sold');

и если какая-либо часть цепочки объектов равна нулю или не определена, она возвращает пустую строку ....

1 голос
/ 17 января 2014

Вы можете использовать мой ObjectPath для запроса больших вложенных документов JSON.Причина, по которой я это делаю, - отсутствие хороших инструментов в языках программирования для работы с JSON, как уже упоминалось в вопросе.

Проект с открытым исходным кодом и по лицензии AGPL.

http://adriank.github.io/ObjectPath/

Реализация Javascript не оптимизирована и ей не хватает половины функциональных возможностей Python, но я хочу добавитьновые вещи, если это необходимо сообществу - просто напишите мне о том, что важно для вас.

0 голосов
/ 03 декабря 2010

Уродливый путь:

for (i in tpsReports) {
  try {
    if(tpsReports[i].personnel_info.productivity.units_sold < 10) {
      fireEmployee();
    }
  } catch (e) {}
}
0 голосов
/ 03 декабря 2010

Мне очень нравится элегантность jsonpath, эквивалентная xpath, но для json.

http://goessner.net/articles/JsonPath/

Там вы можете сделать выражение вроде:

var units_sold = jsonPath(tpsResports, '$.[*].personnel_info.productivity.units_sold');
// units_sold is array of found values... 

(я не проверил дважды свое выражение, это может быть неправильно для того, что вы хотите в вашем примере)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...