Извлечение ключей и значений из вложенного объекта / массива в Javascript

#javascript #typescript #algorithm

#javascript #typescript #алгоритм

Вопрос:

Я работаю над dynamic form builder, где у меня есть элементы формы внутри структуры сетки строк / столбцов, каждый из моих элементов формы (object) имеет специальный ключ с именем model, который определяет имя поля и ключ значения, который определяет его значение. У меня снова есть вложенная форма, которая делает то же самое, мне нужно извлечь эти модель и значения и сделать их объектом, в случае повторителя формы это будет массив. Вот примерный формат данных моей формы:

 [
   {
      "component":"row",
      "attrs":{
         "child_components":[
            {
               "component":"column",
               "attrs":{
                  "child_components":[
                     {
                        "component":"input-text",
                        "attrs":{
                           "child_components":[

                           ],
                           "model":"first_name",
                           "value":"",
                        }
                     },
                     {
                        "component":"input-text",
                        "attrs":{
                           "child_components":[

                           ],
                           "model":"last_name",
                           "value":"",
                        }
                     }
                  ]
               }
            },
            {
               "component":"column",
               "attrs":{
                  "child_components":[
                     {
                        "component":"form-repeater",
                        "attrs":{
                           "child_components":[
                              {
                                 "component":"column",
                                 "attrs":{
                                    "child_components":[
                                       {
                                          "component":"input-text",
                                          "attrs":{
                                             "child_components":[

                                             ],
                                             "model":"name",
                                             "value": ""
                                          }
                                       },
                                       {
                                          "component":"input-text",
                                          "attrs":{
                                             "child_components":[

                                             ],
                                             "model":"url",
                                             "value":""
                                          }
                                       }
                                    ]
                                 }
                              },
                              {
                                 "component":"column",
                                 "attrs":{
                                    "child_components":[
                                       {
                                          "component":"input-text",
                                          "attrs":{
                                             "child_components":[

                                             ],
                                             "model":"name",
                                             "value":""
                                          }
                                       },
                                       {
                                          "component":"input-text",
                                          "attrs":{
                                             "child_components":[

                                             ],
                                             "model":"url",
                                             "value":""
                                          }
                                       }
                                    ]
                                 }
                              }
                           ],
                           "model":"links",
                           "value":""
                        }
                     }
                  ]
               }
            }
         ]
      }
   }
]
  

Для выполнения этого я пытаюсь создать рекурсивную функцию:

 findModel(ele) {
  ele.forEach((element) => {
    if(typeof element.attrs.model !== 'undefined') {
      if(element.component === 'form-repeater') {
        let repeater = [];
        element.attrs.child_components.forEach((rep) => {
          let data = this.findModel(rep.attrs.child_components);
          repeater.push(data);
        })
        const repeaterData = {}
        repeaterData[element.attrs.model] = repeater;
        return repeaterData;
      }
      else {
        const data = {}
        data[element.attrs.model] = element.attrs.value;
        return data;
      }
    }
    else {
      if(typeof element.attrs.child_components !== 'undefined' amp;amp; element.attrs.child_components.length) {
        return this.findModel(element.attrs.child_components);
      }
    }
  })
},
  

И я вызываю эту функцию:

 let data = findModel(form_data)
console.log(data)
//Always comes undefined.
  

Мой окончательный формат данных будет выглядеть примерно так, чего я не могу достичь:

 {
    first_name: '',
    last_name: '',
    links: [
        {name: '', url: ''},
        {name: '', url: ''}
    ]
}
  

Помогите мне в достижении вышеуказанного формата. Любой лучший подход к этому приветствуется. Спасибо.

Комментарии:

1. Рекурсия — правильный подход. Код мог бы быть немного чище, но это не так уж плохо

2. В чем ваш вопрос? Если вы ищете предложения по обзору кода и улучшению, то вы, вероятно, захотите codereview.stackexchange.com

3. @mbdavis мой код не работает. Нужна помощь в получении желаемого формата.

4. @AluanHaddad Ты можешь мне помочь?

5. @AluanHaddad Функция рекурсии не работает, она всегда выбрасывает undefined набор данных. Я виноват, если вы ошиблись.

Ответ №1:

Ваша функция возвращает, undefined потому что у нее нет return инструкции. return Инструкции, которые у вас есть, возвращаются из forEach обратного вызова, который (очевидно) не является той же функцией.

Возврат значения в forEach обратном вызове бесполезен, поскольку это значение исчезает в забвении. forEach Не предназначен для этого.

Вам необходимо:

  1. используйте .map вместо .forEach
  2. возвращает результат .map

Итак:

 return ele.map((element) => {
  

Наконец, в вашей логике обратного вызова есть случай, когда вы не возвращаете значение: у внешнего else блока есть return внутри if блока, но нет return инструкции, когда это внутреннее if условие не выполняется. Таким образом, существует теоретическая возможность того, что обратный вызов в некоторых случаях вернет undefined, что означает, что .map вернет массив с потенциальным неопределенным элементом.

Вы должны убедиться, что все обращения в коде обратного вызова приводят к контролируемому return .