How to replace key in nested object

巧了我就是萌 提交于 2021-01-27 07:13:58

问题


I have an object like this,

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

I just want to change key displayName with label so that my object will look like this,

{
  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
      ]
    }
    ]
  }]
}

I have tried this but not able to replace key in nested array,

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);
}

Please help me sort out this.

Thanks in advance.


回答1:


  1. You have typo in your code. Some variables are shown as displaName instead of displayName.

  2. You need to call a function recursively to work as you intended.

  3. You didn't used newKeys variable for renaming. You just have hard-coded it like newKey = 'label'. But this issue irrelevant with the problem.

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

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

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



回答2:


This is a really generic solution which will traverse through an object and update any object keys that are in the given object literal (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);



回答3:


The existing answers are great, but I can't resist adding a JSON.stringify version:

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);

Obviously, this won't work if you have a value that looks like a key, so it assumes you have a guarantee of predictable data.

If you have multiple replacements you can use

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);

A more traditional recursive option might be the following (still assumes/hardcodes 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));

Iterative:

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));


来源:https://stackoverflow.com/questions/58533695/how-to-replace-key-in-nested-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!