JavaScript - Правильно извлечь свойства глубокого объекта и построить новый объект - PullRequest
0 голосов
/ 27 марта 2020

Предположим, что следующий массив объектов возвращается из API:

const data = [
    { // first item
        meta: {
            stems: [
                "serpentine",
                "serpentinely"
            ]
        },
        hwi: {
            hw: "sep*pen*tine",
            prs: [
                {
                    mw: "ˈsər-pən-ˌtēn",
                    sound: {
                        audio: "serpen02"
                    }
                },
            ]
        },
        shortdef: [
            "of or resembling a serpent (as in form or movement)",
            "subtly wily or tempting",
            "winding or turning one way and another"
        ]
    },
    { // second item
        meta: {
            stems: [
                "moribund",
                "moribundities",
                "moribundity"
            ]
        },
        hwi: {
            hw: "mor*i*bund",
        },
        fl: "adjective"
    }
]

Я хочу создать функцию, которая будет генерировать новый массив объектов. Объекты в этом новом массиве будут состоять из данных старых объектов, только что переставленных. Вот как я ожидаю, что новый массив будет выглядеть, например:

[
  {
    word: 'serpentine',
    definitions: [
      'of or resembling a serpent (as in form or movement)',
      'subtly wily or tempting',
      'winding or turning one way and another'
    ]
  },
  {
    word: 'moribund',
    definitions: [
      'being in the state of dying : approaching death',
      'being in a state of inactivity or obsolescence'
    ],
    partOfSpeech: 'adjective'
  }
]

Я делаю это с помощью следующей функции:

const buildNewData = arr => {
  const newData = []
  arr.forEach(item => {
    newData.push({
      ...item.meta.stems[0] && { word: item.meta.stems[0]},
      ...item.shortdef && { definitions: item.shortdef },
      ...item.fl && { partOfSpeech: item.fl },
      ...item.hwi.prs[0].mw && { pronunciation: item.hwi.prs[0].mw}
    })
  })
  return newData
}
buildNewData(data)

Вам может быть интересно, почему я использую ...item.meta.stems[0] && { word: item.meta.stems[0]} в создании новых объектов. Это делается для проверки, существует ли свойство в исходном объекте. Если он не существует, выражение оценивается как ложное и поэтому не будет добавлено к новому объекту. Первый объект в исходном массиве не имеет свойства fl, поэтому он оценивается как false при создании нового объекта.

Но это не работает при поиске свойства, являющегося массивом. Приведенный выше код завершается ошибкой: TypeError: Cannot read property '0' of undefined. Это связано с тем, что второй элемент не имеет массива prs в свойстве hwi, поэтому поиск не выполняется.

Поскольку я не могу контролировать, какие данные возвращаются из API, как мне написать функцию, которая успешно создает новый массив объектов в указанном мной формате, не вызывая ошибки? У меня уже есть решение не добавлять определенные свойства, если они не существуют, но как мне принять во внимание массивы?

В целом, мне любопытно, существует ли стандартизированный способ извлечения данных из объектов программным способом, который предотвращает возникновение подобных ошибок. Есть ли лучший способ сделать это?

1 Ответ

1 голос
/ 27 марта 2020

Вам необходим дополнительный охранник, поэтому:

...item.hwi.prs[0].mw && { pronunciation: item.hwi.prs[0].mw}

становится

...(Array.isArray(item.hwi.prs) && item.hwi.prs[0].mw) && { pronunciation: item.hwi.prs[0].mw}

, который можно сократить до:

...(item.hwi.prs && item.hwi.prs[0].mw) && { pronunciation: item.hwi.prs[0].mw}

, если вы уверены, что если item.hwi.prs существует, его значением будет массив, имеющий значение 0 , которое можно распространять.

const data = [
    { // first item
        meta: {
            stems: [
                "serpentine",
                "serpentinely"
            ]
        },
        hwi: {
            hw: "sep*pen*tine",
            prs: [
                {
                    mw: "ˈsər-pən-ˌtēn",
                    sound: {
                        audio: "serpen02"
                    }
                },
            ]
        },
        shortdef: [
            "of or resembling a serpent (as in form or movement)",
            "subtly wily or tempting",
            "winding or turning one way and another"
        ]
    },
    { // second item
        meta: {
            stems: [
                "moribund",
                "moribundities",
                "moribundity"
            ]
        },
        hwi: {
            hw: "mor*i*bund",
        },
        fl: "adjective"
    }
];

const buildNewData = arr => {
  const newData = []
  arr.forEach(item => {
    newData.push({
      ...item.meta.stems[0] && { word: item.meta.stems[0]},
      ...item.shortdef && { definitions: item.shortdef },
      ...item.fl && { partOfSpeech: item.fl },
      ...(Array.isArray(item.hwi.prs) && item.hwi.prs[0].mw) && { pronunciation: item.hwi.prs[0].mw}
    })
  })
  return newData
}

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