web-dev-qa-db-fra.com

JavaScript: clé de renommage d'objet

Existe-t-il un moyen intelligent (optimisé) de renommer une clé dans un objet javascript?

Une manière non optimisée serait:

o[ new_key ] = o[ old_key ];
delete o[ old_key ];
203
Jean Vincent

La manière la plus complète (et correcte) de le faire serait, je crois:

if (old_key !== new_key) {
    Object.defineProperty(o, new_key,
        Object.getOwnPropertyDescriptor(o, old_key));
    delete o[old_key];
}

Cette méthode garantit que la propriété renommée se comporte de manière identique par rapport à celle d'origine. 

De plus, il me semble que la possibilité d’englober cela dans une fonction/méthode et de la mettre dans Object.prototype n’a aucune pertinence par rapport à votre question.

144
Valeriu Paloş

Vous pouvez envelopper le travail dans une fonction et l'assigner au prototype Object. Utilisez peut-être le style d’interface fluide pour créer plusieurs flux de renommage.

Object.prototype.renameProperty = function (oldName, newName) {
     // Do nothing if the names are the same
     if (oldName == newName) {
         return this;
     }
    // Check for the old property name to avoid a ReferenceError in strict mode.
    if (this.hasOwnProperty(oldName)) {
        this[newName] = this[oldName];
        delete this[oldName];
    }
    return this;
};

Spécifique ECMAScript 5

J'aurais aimé que la syntaxe ne soit pas si complexe, mais c'est vraiment agréable d'avoir plus de contrôle.

Object.defineProperty(
    Object.prototype, 
    'renameProperty',
    {
        writable : false, // Cannot alter this property
        enumerable : false, // Will not show up in a for-in loop.
        configurable : false, // Cannot be deleted via the delete operator
        value : function (oldName, newName) {
            // Do nothing if the names are the same
            if (oldName == newName) {
                return this;
            }
            // Check for the old property name to 
            // avoid a ReferenceError in strict mode.
            if (this.hasOwnProperty(oldName)) {
                this[newName] = this[oldName];
                delete this[oldName];
            }
            return this;
        }
    }
);
85
ChaosPandion

Si vous modifiez votre objet source, ES6 peut le faire en une seule ligne.

delete Object.assign(o, {[newKey]: o[oldKey] })[oldKey];

Ou deux lignes si vous souhaitez créer un nouvel objet.

const newObject = {};
delete Object.assign(newObject, o, {[newKey]: o[oldKey] })[oldKey];
31
nverba

Dans le cas où quelqu'un aurait besoin de renommer une liste de propriétés: 

function renameKeys(obj, newKeys) {
  const keyValues = Object.keys(obj).map(key => {
    const newKey = newKeys[key] || key;
    return { [newKey]: obj[key] };
  });
  return Object.assign({}, ...keyValues);
}

Usage:

const obj = { a: "1", b: "2" };
const newKeys = { a: "A", c: "C" };
const renamedObj = renameKeys(obj, newKeys);
console.log(renamedObj);
// {A:"1", b:"2"}
25
pomber

Je voudrais juste utiliser la manière ES6(ES2015)!

nous devons suivre le rythme!

const old_obj = {
    k1: `111`,
    k2: `222`,
    k3: `333`
};
console.log(`old_obj =\n`, old_obj);
// {k1: "111", k2: "222", k3: "333"}


/**
 * @author xgqfrms
 * @description ES6 ...spread & Destructuring Assignment
 */

const {
    k1: kA, 
    k2: kB, 
    k3: kC,
} = {...old_obj}

console.log(`kA = ${kA},`, `kB = ${kB},`, `kC = ${kC}\n`);
// kA = 111, kB = 222, kC = 333

const new_obj = Object.assign(
    {},
    {
        kA,
        kB,
        kC
    }
);

console.log(`new_obj =\n`, new_obj);
// {kA: "111", kB: "222", kC: "333"}

 demo screen shortcut

16
xgqfrms-gildata

Je ferais quelque chose comme ça:

function renameKeys(dict, keyMap) {
  return _.reduce(dict, function(newDict, val, oldKey) {
    var newKey = keyMap[oldKey] || oldKey
    newDict[newKey] = val 
    return newDict
  }, {})
}
4
tldr

Si vous ne voulez pas modifier vos données, considérez cette fonction ...

renameProp = (oldProp, newProp, {[oldProp]:old, ...others}) => ({
    [newProp]: old,
    ...others
})

Une explication détaillée de Yazeed Bzadough https://medium.com/front-end-hacking/immutably-rename-object-keys-in-javascript-5f6353c7b6dd


4
Mulhoon

Une variante utilisant un opérateur de déstructuration et d'étalement d'objet:

    const old_obj = {
        k1: `111`,
        k2: `222`,
        k3: `333`
    };


// destructuring, with renaming. The variable rest will hold those values not assigned to kA, kB, or kC.
    const {
        k1: kA, 
        k2: kB, 
        k3: kC,
        ...rest
    } = old_obj;


// now create a new object, with shorthand properties **kA, kB, kC**; 
// spread the remaining properties in the **rest** variable
const newObj = {kA, kB, kC, ...rest};
3
Jeff Lowery

Je dirais qu'il serait préférable d'un point de vue conceptuel de laisser l'ancien objet (celui du service Web) tel quel et de placer les valeurs dont vous avez besoin dans un nouvel objet. Je suppose que vous extrayez des champs spécifiques à un moment ou à un autre de toute façon, sinon sur le client, du moins sur le serveur. Le fait que vous ayez choisi d'utiliser des noms de champs identiques à ceux du service Web, uniquement en minuscules, ne change rien à la situation. Donc, je conseillerais de faire quelque chose comme ça:

var myObj = {
    field1: theirObj.FIELD1, 
    field2: theirObj.FIELD2,
    (etc)
}

Bien sûr, je fais toutes sortes d'hypothèses ici, ce qui peut ne pas être vrai. Si cela ne vous concerne pas ou s'il est trop lent (n'est-ce pas? Je n'ai pas encore testé, mais j'imagine que la différence diminue à mesure que le nombre de champs augmente), veuillez ignorer tout cela :)

Si vous ne le souhaitez pas et que vous ne devez prendre en charge que des navigateurs spécifiques, vous pouvez également utiliser les nouveaux accesseurs pour renvoyer également "majuscule (champ)": voir http://robertnyman.com/2009/05/28/getters-and-setters-with-javascript-code-samples-and-demos/ et les liens de cette page pour plus d'informations.

MODIFIER:

Incroyablement, c'est aussi presque deux fois plus vite, du moins sur mon FF3.5 au travail. Voir: http://jsperf.com/spiny001

3
Spiny Norman

La plupart des réponses ici ne parviennent pas à maintenir l'ordre des paires clé-valeur JS Object. Si vous souhaitez modifier une forme de paire clé-valeur d'objet à l'écran, par exemple, il est important de conserver l'ordre des entrées d'objet.

La manière de ES6 de parcourir en boucle l'objet JS et de remplacer la paire clé-valeur par la nouvelle paire par un nom de clé modifié serait quelque chose comme:

let newWordsObject = {};

Object.keys(oldObject).forEach(key => {
  if (key === oldKey) {
    let newPair = { [newKey]: oldObject[oldKey] };
    newWordsObject = { ...newWordsObject, ...newPair }
  } else {
    newWordsObject = { ...newWordsObject, [key]: oldObject[key] }
  }
});

La solution conserve l'ordre des entrées en ajoutant la nouvelle entrée à la place de l'ancienne.

2
afalak

Certaines des solutions listées sur cette page ont des effets secondaires:

  1. affecter la position de la clé dans l'objet, en l'ajoutant au bas (si cela vous concerne)
  2. ne fonctionnerait pas dans IE9 + (encore une fois, si cela vous concerne)

Voici une solution qui conserve la position de la clé au même endroit et est compatible dans IE9 +, mais doit créer un nouvel objet et peut ne pas être la solution la plus rapide:

function renameObjectKey(oldObj, oldName, newName) {
    const newObj = {};

    Object.keys(oldObj).forEach(key => {
        const value = oldObj[key];

        if (key === oldName) {
            newObj[newName] = value;
        } else {
            newObj[key] = value;
        }
    });

    return newObj;
}

Remarque: IE9 peut ne pas prendre en charge forEach en mode strict.

2
Jasdeep Khalsa

Vous pouvez essayer lodash _.mapKeys .

var user = {
  name: "Andrew",
  id: 25,
  reported: false
};

var renamed = _.mapKeys(user, function(value, key) {
  return key + "_" + user.id;
});

console.log(renamed);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>

2
Yi-Ting Liu

Voici un exemple pour créer un nouvel objet avec des clés renommées.

let x = { id: "checkout", name: "git checkout", description: "checkout repository" };

let renamed = Object.entries(x).reduce((u, [n, v]) => {
  u[`__${n}`] = v;
  return u;
}, {});
1
张焱伟

Bien que cela ne donne pas exactement une meilleure solution pour renommer une clé, cela fournit un moyen rapide et facile pour ES6 de renommer toutes les clés d'un objet sans pour autant transformer les données qu'elles contiennent. 

let b = {a: ["1"], b:["2"]};
Object.keys(b).map(id => {
  b[`root_${id}`] = [...b[id]];
  delete b[id];
});
console.log(b);
1
Tudor Morar

C’est une petite modification que j’ai apportée à la fonction de pomber; ;__. Pour pouvoir prendre un tableau d’objets au lieu d’un objet seul et pouvoir également activer l’index. aussi les "Keys" peuvent être assignés par un tableau

function renameKeys(arrayObject, newKeys, index = false) {
    let newArray = [];
    arrayObject.forEach((obj,item)=>{
        const keyValues = Object.keys(obj).map((key,i) => {
            return {[newKeys[i] || key]:obj[key]}
        });
        let id = (index) ? {'ID':item} : {}; 
        newArray.Push(Object.assign(id, ...keyValues));
    });
    return newArray;
}

tester

const obj = [{ a: "1", b: "2" }, { a: "5", b: "4" } ,{ a: "3", b: "0" }];
const newKeys = ["A","C"];
const renamedObj = renameKeys(obj, newKeys);
console.log(renamedObj);
0
Jasp402

Personnellement, le moyen le plus efficace de renommer des clés dans un objet sans implémenter de plugins et de roues très lourds:

var str = JSON.stringify(object);
str = str.replace(/oldKey/g, 'newKey');
str = str.replace(/oldKey2/g, 'newKey2');

object = JSON.parse(str);

Vous pouvez également l'envelopper dans try-catch si votre objet a une structure non valide. Marche parfaitement :)

0
Novitoll

Ton chemin est optimisé, à mon avis. Mais vous allez vous retrouver avec des clés réorganisées. La clé nouvellement créée sera ajoutée à la fin. Je sais que vous ne devriez jamais vous fier à l'ordre des clés, mais si vous devez le conserver, vous devrez parcourir toutes les clés et construire un nouvel objet un par un en remplaçant la clé en question au cours de ce processus.

Comme ça:

var new_o={};
for (var i in o)
{
   if (i==old_key) new_o[new_key]=o[old_key];
   else new_o[i]=o[i];
}
o=new_o;
0
Tomas M