I have the following structure :
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"
}
I need to find the values of several node in this structure. For this, I use the following function :
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.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;
}
}
When trying this code, the function works as expected :
console.log(PropertyExists(content, 'name'))
Outputs IMB/65004/X/00H7
But when trying this code, I get an error : obj[p][Field] is undefined at line // Error line
console.log(PropertyExists(content, 'buildingName'))
What I dont understand is that the console shows this, indicating that the node was found but when trying to return it id does not exist. The log also shows that before found the node is an object but after it is an array which must be the source of the problem.
Any hint appreciated, thx in advance !
2
Answers
It is true that your code locates the string-typed property correctly, and then returns the corresponding value. But this happens at a deeper recursion level, and the caller of that recursive call ignores the value that is returned and instead expects to find the property at the current nesting level. This is wrong. If the property exists at level 3, then you shouldn’t be looking for it again, and certainly not at level 2.
So just return what you received. Change this:
to this:
On a final note: make sure to compare with
false
explicitly, because a found string property value could be the empty string, which is a falsy value. For that reason you should also change the following:to:
The issue with your JSON object and the function for accessing nested properties likely arise from how arrays are currently handled. Specifically,
buildingName
is nested within an array of objects.To fix this, modify your function to properly handle arrays when traversing the object. Below is an improved version of your
PropertyExists
function: