Изменить имена свойств в объекте, который содержит массивы объектов - PullRequest
2 голосов
/ 14 марта 2020

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

/* an object to refer to where the values are what I want to change the name to */

const camelToSnake = {
  accountId: 'id',
  taxId: 'tax_id',
  individuals: 'customers',
  firstName: 'first_name',
  lastName: 'last_name',
};

/* example object I am passing in to the function */

const obj = {
  accountId: "12345",
  individuals: [
    {name: {firstName: "John", lastName: "Doe"}},
    {name: {firstName: "Bob", lastName: "Smith"}},
  ],
  taxId: "67890",
}

const restructureToSnakeCase = obj => {
  const newObj = {};
  Object.keys(obj).forEach(key => {
    if(typeof obj[key] === 'object'){
      restructureToSnakeCase(obj[key])
    }
    if(Array.isArray(obj[key])){
      obj[key].map(el => {
        restructureToSnakeCase(obj[key])
      })
    }
    newObj[camelToSnake[key] || key] = obj[key]    
  });
  return newObj;
};

С моей пока функцией она может l oop поверх любых объектов первого уровня и изменять имена свойств, но это не так. с любым вложенным значением.

С объектом, который я передаю выше, это результат:

{
  id: "12345",
  customers: [
   {name: {firstName: "John", lastName: "Doe"}},
   {name: {firstName: "Bob", lastName: "Smith"}},
  ],
  tax_id: "67890"
}

В этой ситуации "firstName" и "lastName" должны быть "first_name" и "фамилия".

Я думал с рекурсией, которую я имел выше, что она сможет go в каждый вложенный объект и соответственно изменять имена свойств, но, очевидно, это не работает. Буду очень признателен за любые указатели.

Ответы [ 2 ]

3 голосов
/ 14 марта 2020

Вам необходимо присвоить результаты рекурсивного вызова restructureToSnakeCase их новым ключам на newObj. Вы также должны позаботиться о том, чтобы проверить null (чьи typeof равны obj), и проверить, является ли значение первым массивом (так что вы можете .map его - в противном случае, если это объект, просто сделать простой рекурсивный вызов).

/* an object to refer to where the values are what I want to change the name to */

const camelToSnake = {
  accountId: 'id',
  taxId: 'tax_id',
  individuals: 'customers',
  firstName: 'first_name',
  lastName: 'last_name',
};

/* example object I am passing in to the function */

const obj = {
  accountId: "12345",
  individuals: [
    {name: {firstName: "John", lastName: "Doe"}},
    {name: {firstName: "Bob", lastName: "Smith"}},
  ],
  taxId: "67890",
}

const restructureToSnakeCase = obj => {
  if (typeof obj !== 'object' || obj === null) {
    return obj;
  }
  const newObj = {};
  Object.entries(obj).forEach(([key, val]) => {
    const newKey = camelToSnake[key] || key;
    if (Array.isArray(val)) {
      newObj[newKey] = val.map(restructureToSnakeCase)
    } else if (typeof val === 'object' && val !== null) {
      newObj[newKey] = restructureToSnakeCase(val)
    } else {
      newObj[newKey] = val;
    }
  });
  return newObj;
};
console.log(restructureToSnakeCase(obj));

Я бы предпочел использовать Object.fromEntries, это выглядит намного чище:

/* an object to refer to where the values are what I want to change the name to */

const camelToSnake = {
  accountId: 'id',
  taxId: 'tax_id',
  individuals: 'customers',
  firstName: 'first_name',
  lastName: 'last_name',
};

/* example object I am passing in to the function */

const obj = {
  accountId: "12345",
  individuals: [
    {name: {firstName: "John", lastName: "Doe"}},
    {name: {firstName: "Bob", lastName: "Smith"}},
  ],
  taxId: "67890",
}

const restructureToSnakeCase = item => {
  if (typeof item !== 'object' || item === null) {
    return item;
  }
  if (Array.isArray(item)) {
    return item.map(restructureToSnakeCase);
  }
  return Object.fromEntries(
    Object.entries(item).map(([key, val]) => [
      camelToSnake[key] || key,
      restructureToSnakeCase(val)
    ])
  );
};

console.log(restructureToSnakeCase(obj));
1 голос
/ 14 марта 2020

Небольшие изменения в вашем коде, упомянутые встроенные комментарии 1) - 4)
В основном есть одна локальная переменная value, получить обновленное значение и присвоить обратно ключу.

const camelToSnake = {
  accountId: "id",
  taxId: "tax_id",
  individuals: "customers",
  firstName: "first_name",
  lastName: "last_name"
};

const obj = {
  accountId: "12345",
  individuals: [
    { name: { firstName: "John", lastName: "Doe" } },
    { name: { firstName: "Bob", lastName: "Smith" } }
  ],
  taxId: "67890"
};

const restructureToSnakeCase = obj => {
  const newObj = {};
  Object.keys(obj).forEach(key => {
    let value = obj[key]; // 1. initialize value
    if (typeof obj[key] === "object") {
      value = restructureToSnakeCase(obj[key]); // 2. update value
    }
    if (Array.isArray(obj[key])) {
      value = obj[key].map(el => restructureToSnakeCase(el)); // 3. pass el and not obj[key]
    }
    newObj[camelToSnake[key] || key] = value; // 4. update value
  });
  return newObj;
};

console.log(restructureToSnakeCase(obj));

Если вы также хотите создать случай змеи из camelCase, отметьте это.

function camelCaseTo_snake_case(str) {
  const [start, end] = ["A", "Z"];
  const words = [];

  let word = "";
  for (let i = 0; i < str.length; i++) {
    if (str[i] >= start && str[i] <= end) {
      if (word) {
        words.push(word);
        word = "";
      }
    }
    word = `${word}${str[i]}`;
  }
  words.push(word);
  return words.map(word => word.toLowerCase()).join("_");
}

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