2

I need to go through the json object and find keys-objects, keys-arrays whose size matches a given value.

I can't understand where to set the conditions.

function traverse(obj, size) {
    for (let key in obj) {
        if (typeof obj[key] === "object" && obj[key] != null) {
            traverse(obj[key]);
            if (Object.keys(obj[key]).length > size) {
                console.log(key);
            } else if (Array.isArray(obj[key])) {
                if (obj[key].length > size) { 
                    console.log(key);
                }
            } 
        }
    }
}

I've tried rearranging the if conditions, but it doesn't give any good results

Sample Test Object

let objTest = {
    "id": "66100c8e58d0a40e97ce7753",
    "createdBy": "crm1",
    "attributes": {
        "accountsInfoMessages": [{
            "valueOzb": "Mijozning holati yoritilgan. Hisob yaratish mumkin emas. Mijoz ma'lumotlarini to'ldiring. Buning uchun \"Kartochkani tanrirlash\" tugmasini bosing.",
            "code": "notCreateAccount",
        }, {
            "valueOzb": "Mijozning holati yoritilgan. Hisob yaratish mumkin emas. Mijoz ma'lumotlarini to'ldiring. Buning uchun \"Kartochkani tanrirlash\" tugmasini bosing.",
            "code": "notCreateAccount",
        }, {
            "valueOzb": "Mijozning holati yoritilgan. Hisob yaratish mumkin emas. Mijoz ma'lumotlarini to'ldiring. Buning uchun \"Kartochkani tanrirlash\" tugmasini bosing.",
            "code": "notCreateAccount",
        }],
        "selectedCardProduct": null,
        "homePageId": null,
        "branch": null,
        "customerId": "1111",
        "selectForCurrencyTest": "111",
        "selectForFiltersCardType": {
            "values": [{
                "code": "01",
                "valueOzb": "HUMO"
            }, {
                "code": "02",
                "valueOzb": "UzCard",
            }, {
                "code": "03",
                "valueOzb": "Visa"
            }],
        },
        "selectForCurrency": [{
            "valueOzb": "Andor pesetasi",
            "code": "ADP"
        }, {
            "code": "AED",
            "valueOzb": "Birlashgan Arab Amirliklari dirhami"
        }, {
            "valueOzb": "Afg'ani",
            "code": "AFA"
        }, ]
    },
    "selectForCurrency": "Test"
}
1
  • 1
    please add some data as well. and the wanted result. Commented Apr 23 at 16:07

3 Answers 3

1

I've corrected some parts of your function as per my understanding. This should work. If it doesn't, let me know in the comments what error/bug you encounter. Preferably, add an instance/simplified example of the object you're traversing to your question.

EDIT: Here's the final draft of a tested solution:

/* Test Data: */
const testObject = {
  owner: 'John Doe',
  prices: [200, 450, -400, 3000, -650, -130, 70, 1300],
  interestRate: 1.2, // %
  pin: 1111,
  nullVal: null,
  objOuter: {
    one: 1,
    two: 2,
    three: 3,
    arr1: [200, 450, -650],
    inner: {
      uno: 1,
      dos: 2,
      tres: 3,
      arr2: [-400, 3000],
      innermost: {
        ich: 1,
        ni: 2,
        san: 3,
        arr3: [-130, 70, 1300],
      },
    },
  },
};

/* Function: */
function traverse(obj, size) {
  for (const [key, val] of Object.entries(obj)) {
    if (!val) continue;
    if (Array.isArray(val) && val.length > size) {
      console.log(key);
      val.forEach(function (el, i) {
        if (typeof el === 'object') traverse(el, size);
      });
    }
    if (typeof val === 'object' && !Array.isArray(val) && Object.keys(val).length > size) {
      console.log(key);
      traverse(val, size);
    }
  }
}
traverse(testObject, 3); // Function call

4
  • Thank you. Looks like it's working. The problem was only if value is null, when checking for an array - Object.keys(val) could not convert null. I added a check for null if (typeof val === 'object' && val != null && !Array.isArray(val) && Object.keys(val).length > size) Commented Apr 24 at 8:15
  • 1
    You don't need to check for 'null' values because the condition (typeof val === "object") takes care of it. If val is an object type, its value will not be null even if it is empty. Just like how console.log({}); and console.log([]); do not print null. If val is an empty object/array, the condition that checks its size/length will be false and val will be ignored. Commented Apr 24 at 8:27
  • 1
    Without the check, it throws 'TypeError: Cannot convert undefined or null to object ' on Object.keys(val). I have attached a sample object. Commented Apr 24 at 8:33
  • 1
    Yes. That seems to be the case. To fix it properly, I suggest adding this line: if (!val) continue; to the top of the for-of loop in the function. I'm adding this line in the final edit to the answer. Commented Apr 24 at 8:53
1

You are calling traverse with only one argument.

if (typeof obj[key] === "object" && obj[key] != null) {
    traverse(obj[key]); // here !
     //... rest of the code
}

it should be

traverse(obj[key], size);

Please privide object example with desired result to verify the logic

1
  1. You should pass the arguments to the recursive calls
  2. You could add an accumulator to collect the result

let objTest={id:"66100c8e58d0a40e97ce7753",createdBy:"crm1",attributes:{accountsInfoMessages:[{valueOzb:"Mijozning holati yoritilgan. Hisob yaratish mumkin emas. Mijoz ma'lumotlarini to'ldiring. Buning uchun \"Kartochkani tanrirlash\" tugmasini bosing.",code:"notCreateAccount"},{valueOzb:"Mijozning holati yoritilgan. Hisob yaratish mumkin emas. Mijoz ma'lumotlarini to'ldiring. Buning uchun \"Kartochkani tanrirlash\" tugmasini bosing.",code:"notCreateAccount"},{valueOzb:"Mijozning holati yoritilgan. Hisob yaratish mumkin emas. Mijoz ma'lumotlarini to'ldiring. Buning uchun \"Kartochkani tanrirlash\" tugmasini bosing.",code:"notCreateAccount"}],selectedCardProduct:null,homePageId:null,branch:null,customerId:"1111",selectForCurrencyTest:"111",selectForFiltersCardType:{values:[{code:"01",valueOzb:"HUMO"},{code:"02",valueOzb:"UzCard"},{code:"03",valueOzb:"Visa"}]},selectForCurrency:[{valueOzb:"Andor pesetasi",code:"ADP"},{code:"AED",valueOzb:"Birlashgan Arab Amirliklari dirhami"},{valueOzb:"Afg'ani",code:"AFA"},]},selectForCurrency:"Test"};

function traverse(obj, size, key = null, result = []) {
  if(Array.isArray(obj)){
    obj.forEach((item,i) => traverse(item, size, i, result));
    obj.length > size && key && result.push(key);
  } else if (obj && typeof obj === "object") {
    const keys = Object.keys(obj);
    keys.forEach(key => traverse(obj[key], size, key, result));
    keys.length > size && key && result.push(key);
  }
  return result;
}

console.log(traverse(objTest, 1));

1
  • Thank you for your reply. The function returns an empty array. I have not been able to debug where the error is. I have attached a test object. Commented Apr 24 at 8:29

Not the answer you're looking for? Browse other questions tagged or ask your own question.