Мне нужно пройтись по json-объекту и найти ключи-объекты, ключи-массивы, размер которых соответствует заданному значению.
Не могу понять где поставить условия.
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.info(key);
} else if (Array.isArray(obj[key])) {
if (obj[key].length > size) {
console.info(key);
}
}
}
}
}
Я пробовал переставлять условия if, но это не дало хороших результатов.
Образец тестового объекта
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"
}
Вы вызываете traverse только с одним аргументом.
if (typeof obj[key] === "object" && obj[key] != null) {
traverse(obj[key]); // here !
//... rest of the code
}
должен быть
traverse(obj[key], size);
Пожалуйста, предоставьте пример объекта с желаемым результатом, чтобы проверить логику.
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.info(traverse(objTest, 1));
Спасибо за ваш ответ. Функция возвращает пустой массив. Я не смог отладить, где находится ошибка. Я прикрепил тестовый объект.
Насколько я понимаю, я исправил некоторые части вашей функции. Это должно сработать. Если это не так, дайте мне знать в комментариях, с какой ошибкой/ошибкой вы столкнулись. Предпочтительно добавить в свой вопрос экземпляр/упрощенный пример объекта, который вы проходите.
Обновлено: Вот окончательный вариант протестированного решения:
/* 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.info(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.info(key);
traverse(val, size);
}
}
}
traverse(testObject, 3); // Function call
Спасибо. Похоже, это работает. Проблема заключалась только в том, что при проверке массива значение равно нулю: Object.keys(val) не может преобразовать значение null. Я добавил проверку на null if (typeof val === 'object' && val != null && !Array.isArray(val) && Object.keys(val).length > size)
Вам не нужно проверять наличие «нулевых» значений, потому что об этом позаботится условие (typeof val === "object")
. Если val
является типом object
, его значение не будет нулевым, даже если оно пустое. Точно так же, как console.info({});
и console.info([]);
не печатают null
. Если val
— пустой объект/массив, условие, проверяющее его размер/длину, будет false
и val
будет игнорироваться.
Без проверки выдается сообщение «TypeError: невозможно преобразовать неопределенное или нулевое значение в объект» в Object.keys(val). Я прикрепил образец объекта.
Да. Кажется, это так. Чтобы исправить это правильно, я предлагаю добавить эту строку: if (!val) continue;
в начало цикла for-of
в функции. Я добавляю эту строку в окончательную версию ответа.
пожалуйста, добавьте некоторые данные. и желаемый результат.