You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript递归遍历查找节点值时出现undefined错误排查

问题:递归查找JSON节点值时数组处理导致的undefined错误

我有如下嵌套JSON结构:

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函数,代码如下:

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') {return obj[Field].toLowerCase();}for (var p in obj) {console.log(p)if ($S.PropertyExists(obj[p], Field)) {console.log(obj[p])console.log(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.log(PropertyExists(content, 'name'))时能正常返回IMB/65004/X/00H7,但执行console.log(PropertyExists(content, 'buildingName'))时抛出错误:obj[p][Field] is undefined。日志显示节点已被找到,但因为数组处理的问题无法返回正确值,求解决提示。

问题分析与修复方案

错误原因

  1. 未处理数组类型节点:当遍历到place、geographicSubAddress这类数组时,obj[p]是数组对象,你直接将其当作普通对象处理。递归找到buildingName后,试图通过obj[p][Field]取值,但数组本身没有buildingName属性,因此报undefined。
  2. 递归返回逻辑错误:递归调用$S.PropertyExists(obj[p], Field)返回有效值时,你没有直接返回这个结果,反而尝试重新通过obj[p][Field]取值,这在数组场景下必然失败。

修复后的函数

PropertyExists: function(obj, Field) {
    var DataField = Field.split('.');
    // 处理单层字段(如'buildingName')
    if (DataField.length === 1) {
        if (typeof obj === 'object' && obj !== null) {
            // 检查当前对象是否包含目标字段且为字符串
            if (obj.hasOwnProperty(Field) && typeof obj[Field] === 'string') {
                return obj[Field].toLowerCase();
            }
            // 遍历对象所有属性
            for (var p in obj) {
                var val = obj[p];
                // 处理数组:遍历每个元素递归查找
                if (Array.isArray(val)) {
                    for (var item of val) {
                        var result = $S.PropertyExists(item, Field);
                        if (result !== false) {
                            return result;
                        }
                    }
                } 
                // 处理子对象:直接递归查找
                else if (typeof val === 'object' && val !== null) {
                    var result = $S.PropertyExists(val, Field);
                    if (result !== false) {
                        return result;
                    }
                }
            }
        }
        return false;
    } 
    // 处理嵌套字段(如'place.name')
    else {
        if (typeof obj === 'object' && obj !== null) {
            // 检查嵌套路径是否存在且目标值为字符串
            if (obj.hasOwnProperty(DataField[0]) && 
                typeof obj[DataField[0]] === 'object' && 
                obj[DataField[0]] !== null &&
                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) {
                var val = obj[p];
                if (Array.isArray(val)) {
                    for (var item of val) {
                        var result = $S.PropertyExists(item, Field);
                        if (result !== false) {
                            return result;
                        }
                    }
                } else if (typeof val === 'object' && val !== null) {
                    var result = $S.PropertyExists(val, Field);
                    if (result !== false) {
                        return result;
                    }
                }
            }
        }
        return false;
    }
}

关键修复点

  • 新增数组处理逻辑:遍历对象属性时,判断如果是数组则逐个遍历元素进行递归查找,覆盖JSON中的数组嵌套场景。
  • 修正递归返回逻辑:递归调用后直接返回结果,不再尝试通过obj[p][Field]重新取值,避免数组场景下的属性不存在错误。
  • 增强空值判断:处理嵌套字段时,增加对中间对象的非空校验,避免空指针异常。

内容的提问来源于stack exchange,提问作者BlackPage

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 03:34:54