如何替换嵌套对象中的键

时间:2019-10-24 03:23:32

标签: javascript javascript-objects

我有一个这样的物体

{
  id: '1',
  displaName: 'A',
  children: [
  {
    id: '2',
    displayName: 'B',
    children: [
    {
      id: '3',
      displayName: 'C',
      children: [
            //More nested array here
      ]
    }
    ]
  }]
}

我只想用displayName更改键label,以便我的对象看起来像这样,

{
  id: '1',
  label: 'A',  //change key displayName => label
  children: [
  {
    id: '2',
    label: 'B',  //change key displayName => label
    children: [
    {
      id: '3',
      label: 'C',  //change key displayName => label
      children: [
            //More nested array here
      ]
    }
    ]
  }]
}

我已经尝试过了,但是无法替换嵌套数组中的键,

const newKeys = { displaName: "label"};
const renamedObj = renameKeys(resp.data, newKeys);
console.log(renamedObj);

function renameKeys(obj, newKeys) {
  const keyValues = Object.keys(obj).map(key => {
    console.log(key);
    let newKey = null
    if(key === 'displayName'){
       newKey = 'label'
    }else{
       newKey = key
    }
    console.log(newKey);
    return { [newKey]: obj[key] };
  });
  return Object.assign({}, ...keyValues);
}

请帮助我解决这个问题。

谢谢。

3 个答案:

答案 0 :(得分:3)

  1. 您的代码中有错字。某些变量显示为const desktopMetricsForm = document.getElementById("desktopMetricsForm"); desktopMetricsForm.addEventListener('submit', function (event) { const formattedFormData = new FormData(form); desktopMetricsPostData(formattedFormData); return false; }) async function desktopMetricsPostData() { const response = await fetch('api/get_desktop_metrics.php', { method: 'GET', headers: { "Content-Type": "application/x-www-form-urlencoded", }, body: formattedFormData }); const data = await response.text(); document.getElementById("desktopMetricsTable").innerHTML = data; } 而不是displaName

  2. 您需要递归调用函数才能按预期工作。

  3. 您没有使用displayName变量进行重命名。您只是像newKeys一样对其进行了硬编码。但是这个问题与问题无关。

newKey = 'label'

答案 1 :(得分:0)

这是一个非常通用的解决方案,它将遍历对象并更新给定对象文字(keysToUpdate)中的所有对象键。

const orig = {
  id: '1',
  displayName: 'A',
  children: [{
    id: '2',
    displayName: 'B',
    children: [{
      id: '3',
      displayName: 'C',
      children: [
        //More nested array here
      ]
    }]
  }]
};

const updateDisplayNameToLabel = (val, keysMap) => {
  if (val == null) return null;
  if (Array.isArray(val)) {
    return val.map(item => updateDisplayNameToLabel(item, keysMap));
  } else if (typeof val == "object") {
    return Object.keys(val).reduce((obj, key) => {
      const propKey = updateDisplayNameToLabel(key, keysMap);
      const propVal = updateDisplayNameToLabel(val[key], keysMap);
      obj[propKey] = propVal;
      return obj;
    }, {});
  } else if (typeof val === "string") {
    return keysMap[val] || val;
  }
  return val;
}

const keysToUpdate = {
  displayName: 'label',
  children: 'items'
};

const updated = updateDisplayNameToLabel(orig, keysToUpdate);

console.log(updated);

答案 2 :(得分:0)

现有的答案很好,但是我无法抗拒添加JSON.stringify版本:

const data = { id: '1', displayName: 'A', children: [ { id: '2', displayName: 'B', children: [ { id: '3', displayName: 'C', children: [] }] }] };
const result = JSON.parse(JSON.stringify(data).replace(/"displayName":/g, '"value":'));
console.log(result);

很显然,如果您的值看起来像键,那么这将无法正常工作,因此它假定您可以保证可预测的数据。

如果您有多个替代品,可以使用

const data = { id: '1', displayName: 'A', children: [ { id: '2', displayName: 'B', children: [ { id: '3', displayName: 'C', children: [] }] }] };
const swaps = {displayName: "foo", children: "baz", id: "corge"};
const pattern = new RegExp(
  Object.keys(swaps).map(e => `(?:"(${e})":)`).join("|"), "g"
);
const result = JSON.parse(
  JSON.stringify(data).replace(pattern, m => `"${swaps[m.slice(1,-2)]}":`)
);
console.log(result);

更传统的递归选项可能是以下内容(仍然假设/硬编码为children):

const changeKey = (node, keySubs) => 
  Object.entries(keySubs).reduce((a, [oldKey, newKey]) => {
    a[newKey] = a[oldKey];
    delete a[oldKey];
    return a;
  }, {...node, children: node.children.map(e => changeKey(e, keySubs))})
;

const data = { id: '1', displayName: 'A', children: [ { id: '2', displayName: 'B', children: [ { id: '3', displayName: 'C', children: [] }] }] };
const swaps = {displayName: "label", id: "better id"};
console.log(changeKey(data, swaps));

迭代:

const changeKey = (node, keySubs) => {
  const result = {children: []};
  const stack = [[node, result]];

  while (stack.length) {
    const [curr, parent] = stack.pop();
    const child = Object.entries(keySubs)
      .reduce((a, [oldKey, newKey]) => {
        a[newKey] = a[oldKey];
        delete a[oldKey];
        return a;
      }, {...curr, children: []})
    ;
    parent.children.push(child);
    stack.push(...curr.children.map(e => [e, child]));
  }

  return result;
};

const data = { id: '1', displayName: 'A', children: [ { id: '2', displayName: 'B', children: [ { id: '3', displayName: 'C', children: [] }] }] };
const swaps = {displayName: "label", id: "better id"};
console.log(changeKey(data, swaps));