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 ];
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.
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;
}
}
);
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];
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"}
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"}
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
}, {})
}
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
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};
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
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.
Certaines des solutions listées sur cette page ont des effets secondaires:
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.
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>
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;
}, {});
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);
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);
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 :)
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;