Javascript: найти значение узла посредством рекурсивной итерации

У меня есть следующая структура:

var content = {
    "id": "RkktMTA1OC0wNTE3QElNQi82NTAwNC9YLzAwSDc",
    "name": "FI-1058-0517",
    "category": "FTTH",
    "place": {
      "id": "SU1CLzY1MDA0L1gvMDBINw",
      "href": "/geographicSite/SU1CLzY1MDA0L1gvMDBINw",
      "name": "IMB/65004/X/00H7",
      "isSiteInfoAvailable": true,
      "place": [
        {
          "geographicSubAddress": [
            {
              "internalBuildingReference": "SSS0100000000000198332600",
              "internalFloorReference": "",
              "buildingName": "_NA_",
              "levelNumber": "0",
              "levelType": "floor",
              "subUnit": [
                {
                  "subUnitNumber": "_NA_",
                  "subUnitType": "staircase",
                  "internalReference": "SSS0100000000000198332601",
                  "@type": "GeographicSubAddressUnitExtended",
                  "@baseType": "GeographicSubAddressUnit"
                }
              ],
              "@type": "GeographicSubAddressBuilding"
            }
          ],
          "@type": "GeographicAddress"
        }
      ],
      "relatedParty": [
        {
          "id": "FI",
          "@referredType": "OI"
        }
      ],
      "@type": "GeographicSiteBuilding",
      "@baseType": "GeographicSite"
    },
    "resourceStatus": "En service",
    "usageState": "Actif",
    "developerOutletReference": "",
    "toBeTicketed": false,
    "resourceRelationship": [
      {
        "id": "PT 000629",
        "relationshipType": "Connected PBO",
        "href": "/resource/pbo/UFQgMDAwNjI5QEZJLTY1MDU2LTAwMDM",
        "@referredType": "ResourcePbo"
      },
      {
        "id": "FI-65056-0003",
        "relationshipType": "Connected PM",
        "href": "/resource/pm/RkktNjUwNTYtMDAwMw",
        "@referredType": "ResourcePm"
      }
    ],
    "nonOapcInfo": {
      "startOperatingDate": "2023-04-01",
      "endOperatingDate": null,
      "predecessorIAR": ""
    },
    "hasFiberOpticDrawer": "",
    "description": "",
    "@baseType": "Resource",
    "@type": "ResourcePto",
    "FTTHLineStatus": [
      "existant",
      "actif",
      "raccordable",
      "commercialisable"
    ],
    "href": "/resource/pto/RkktMTA1OC0wNTE3QElNQi82NTAwNC9YLzAwSDc"
  }

Мне нужно найти значения нескольких узлов в этой структуре. Для этого я использую следующую функцию:

PropertyExists: function (obj, Field){
    var DataField = Field.split('.');

    if (DataField.length == 1){
        if (typeof obj === 'object' && obj !== null) {

            if (obj.hasOwnProperty(Field) && typeof obj[Field] === 'string') {              // if this object already contains the property, we are done
              return obj[Field].toLowerCase();
            }
            for (var p in obj) {                         // otherwise iterate on all the properties of this object.
                console.info(p)
                if ($S.PropertyExists(obj[p], Field)) { 
                    console.info(obj[p])
                    console.info(Field)
                    return obj[p][Field].toLowerCase(); // Error line
                }
            }
        }
        return false;
    } else {
        if (typeof obj === 'object' && obj !== null) {
            if (obj.hasOwnProperty(DataField[0]) && obj[DataField[0]].hasOwnProperty(DataField[1]) && typeof obj[DataField[0]][DataField[1]] === 'string') {
              return obj[DataField[0]][DataField[1]].toLowerCase();
            }
            for (var p in obj) {
                if ($S.PropertyExists(obj[p], Field)) { 
                    return obj[p][DataField[0]][DataField[1]].toLowerCase();
                }
            }
        }
        return false;
    }
}

При попытке использовать этот код функция работает как положено:

console.info(PropertyExists(content, 'name'))

Выходы IMB/65004/X/00H7

Но при попытке использовать этот код я получаю сообщение об ошибке: obj[p][Field] не определено в строке // Строка ошибки

console.info(PropertyExists(content, 'buildingName'))

Чего я не понимаю, так это того, что консоль показывает это, указывая, что узел был найден, но при попытке вернуть его идентификатор не существует. Журнал также показывает, что до обнаружения узел является объектом, но после этого он представляет собой массив, который должен быть источником проблемы.

Любая подсказка приветствуется, заранее спасибо!

Можете ли вы описать ожидаемый результат? В вашем вопросе подробно описан формат данных и попытка кода, но неточно указано, какова цель.

Rory McCrossan 09.07.2024 14:41

Также обратите внимание, что в приведенном примере выводится fi-1058-0517, а не IMB/65004/X/00H7.

Rory McCrossan 09.07.2024 14:43

Некоторые свойства контента являются массивами или содержат массивы. Вы говорите «узнайте название здания». Что делать, если в контенте есть 4 названия зданий?

James 09.07.2024 14:54
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
3
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это правда, что ваш код правильно находит свойство строкового типа, а затем возвращает соответствующее значение. Но это происходит на более глубоком уровне рекурсии, и вызывающая сторона этого рекурсивного вызова игнорирует возвращаемое значение и вместо этого ожидает найти свойство на текущем уровне вложенности. Это не верно. Если свойство существует на уровне 3, то вам не следует искать его снова, и тем более на уровне 2.

Так что просто верните то, что получили. Измените это:

if ($S.PropertyExists(obj[p], Field)) { 
    console.info(obj[p])
    console.info(Field)
    return obj[p][Field].toLowerCase(); // Error line
}

к этому:

const result = $S.PropertyExists(obj[p], Field);
if (result !== false) {
    return result; // We already got the result, so just bubble it up.
}

И последнее замечание: обязательно сравнивайте с false явно, поскольку найденное значение свойства строки может быть пустой строкой, которая является ложным значением. По этой причине вам также следует изменить следующее:

if ($S.PropertyExists(obj[p], Field)) { 

к:

if ($S.PropertyExists(obj[p], Field) !== false) { 

Другие вопросы по теме