Рекурсивные данные в JSON объекте - PullRequest
5 голосов
/ 14 февраля 2020
{
"groups": [
    {
        "name": "Event",
        "groups": [
            {
                "name": "Service",
                "subscriptions": [
                    {
                        "topic": "SERVICE_STATUS_PRESETS"
                    },
                    {
                        "topic": "AIRCRAFT_ACTIVATION",

                    },
                    {
                        "topic": "OUT_OF_SERVICE",

                    }
                ]
            }
        ]
    },
    {
        "name": "Enquiries",
        "groups": [
            {
                "name": "Service-related",
                "subscriptions": [
                    {

                        "topic": "PROMO_CODES_REQUESTS",

                    }
                ]
            }
        ]
    }
],
"subscriptions": [
    {
        "topic": "BANNERS",
    },
    {
        "topic": "DOCUMENTS",
    },
    {
        "topic": "USER",
    }
]

}

ОК, ребята, у меня есть такая JSON структура, которая мне нужна: вернуть все темы в массиве, в этом примере это будет:

["SERVICE_STATUS_PRESETS", "AIRCRAFT_ACTIVATION", "OUT_OF_SERVICE", "PROMO_CODES_REQUESTS", "BANNERS", "DOCUMENTS", "USER"]

я пробую только последние рекурсивные вызовы, как это, хотя я три записи:

getRecursive() {
if (Array.isArray(data)) {
       for (let i = 0; i < data.length; i++) {
         if (data[i].subscriptions) {
           return data[i].subscriptions.map((val: SubscriptionGroupDetails) => val.topic);
         } else if (data[i].groups) {
           return this.getAllTopics(data[i].groups);
         }
       }
     }
     if (data && data.groups) {
      return this.getAllTopics(data.groups);
     }
     return data.subscriptions.map((val: SubscriptionGroupDetails) => val.topic);
}

Ответы [ 4 ]

3 голосов
/ 14 февраля 2020

Вы можете использовать рекурсивный подход и проверить

  • , если передаваемые данные не являются объектом для проверки, а затем вернуть с пустым массивом
  • , если объект имеет требуемый свойство, затем вернуть массив со значением topic,
  • или получить значения и сделать рекурсивный вызов функции и вернуть массив с результатом.

function getTopics(object) {
    if (!object || typeof object !== 'object') return [];
    if ('topic' in object) return [object.topic];
    return Object.values(object).reduce((r, v) => [...r, ...getTopics(v)], []);
}

var data = { groups: [{ name: "Event", groups: [{ name: "Service", subscriptions: [{ topic: "SERVICE_STATUS_PRESETS" }, { topic: "AIRCRAFT_ACTIVATION" }, { topic: "OUT_OF_SERVICE" }] }] }, { name: "Enquiries", groups: [{ name: "Service-related", subscriptions: [{ topic: "PROMO_CODES_REQUESTS" }] }] }], subscriptions: [{ topic: "BANNERS" }, { topic: "DOCUMENTS" }, { topic: "USER" }] },
    result = getTopics(data);

console.log(result);
0 голосов
/ 14 февраля 2020

Эта версия, которая использует функциональный подход, если вы заинтересованы. Выше есть и другие, но это просто другой взгляд на это.

const recursion = object => Object.entries(object).map(([a, b]) => {
  if (a === 'topic') return b;
  if (Array.isArray(b)) return b.map(recursion);
  return [];
}).flat(Infinity);

recursion(obj);
0 голосов
/ 14 февраля 2020

используйте это:

function getTopics(obj){
   if(typeof obj !== 'object') return [];
   if(obj.topic) return [obj.topic];
   var res = [];
   for(var i in obj){
     res.push(...getTopics(obj[i]));
   }
   return res;
}

Рабочий пример:

const topics = {
"groups": [
    {
        "name": "Event",
        "groups": [
            {
                "name": "Service",
                "subscriptions": [
                    {
                        "topic": "SERVICE_STATUS_PRESETS"
                    },
                    {
                        "topic": "AIRCRAFT_ACTIVATION",

                    },
                    {
                        "topic": "OUT_OF_SERVICE",

                    }
                ]
            }
        ]
    },
    {
        "name": "Enquiries",
        "groups": [
            {
                "name": "Service-related",
                "subscriptions": [
                    {

                        "topic": "PROMO_CODES_REQUESTS",

                    }
                ]
            }
        ]
    }
],
"subscriptions": [
    {
        "topic": "BANNERS",
    },
    {
        "topic": "DOCUMENTS",
    },
    {
        "topic": "USER",
    }
]
}

function getTopics(obj){
  if(typeof obj !== 'object') return [];
  if(obj.topic) return [obj.topic];
  var res = [];
  for(var i in obj){
    res.push(...getTopics(obj[i]));
  }
  return res;
}


console.log(getTopics(topics));
0 голосов
/ 14 февраля 2020

РЕДАКТИРОВАТЬ: Добавлен еще один способ сделать это с .reduce ()

Вы можете создать пустой массив из topics, а затем перемещаться по вложенным рекурсивно структурировать, добавляя topi c каждый раз, когда вы сталкиваетесь с ним, используя javascript .forEach () для циклического перебора любых вложенных groups или subscriptions.

let topics = [];

let findTopics = obj => {
   if (obj.groups) {
      obj.groups.forEach(findTopics);
   }
   if (obj.subscriptions) {
      obj.subscriptions.forEach(findTopics);
   }
   if (obj.topic) {
      topics.push(obj.topic);
   }
}

findTopics(data);

Или, возможно, более аккуратный способ использования .reduce () :

let findTopicsRecursive = (topics, obj) => {
   if (obj.groups) {
      topics = obj.groups.reduce(findTopicsRecursive, topics);
   }
   if (obj.subscriptions) {
      topics = obj.subscriptions.reduce(findTopicsRecursive, topics);
   }
   if (obj.topic) {
      topics.push(obj.topic);
   }
   return topics;
}

let findTopics = data => findTopicsRecursive([], data);

let topics = findTopics(data);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...