JavaScript: Object Rename Key
Solution 1
The most complete (and correct) way of doing this would be, I believe:
if (old_key !== new_key) {
Object.defineProperty(o, new_key,
Object.getOwnPropertyDescriptor(o, old_key));
delete o[old_key];
}
This method ensures that the renamed property behaves identically to the original one.
Also, it seems to me that the possibility to wrap this into a function/method and put it into Object.prototype
is irrelevant regarding your question.
Solution 2
If you're mutating your source object, ES6 can do it in one line.
delete Object.assign(o, {[newKey]: o[oldKey] })[oldKey];
Or two lines if you want to create a new object.
const newObject = {};
delete Object.assign(newObject, o, {[newKey]: o[oldKey] })[oldKey];
Solution 3
You could wrap the work in a function and assign it to the Object
prototype. Maybe use the fluent interface style to make multiple renames flow.
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;
};
ECMAScript 5 Specific
I wish the syntax wasn't this complex but it is definitely nice having more control.
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;
}
}
);
Solution 4
In case someone needs to rename a list of properties:
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"}
Solution 5
To add prefix to each key:
const obj = {foo: 'bar'}
const altObj = Object.fromEntries(
Object.entries(obj).map(([key, value]) =>
// Modify key here
[`x-${key}`, value]
)
)
// altObj = {'x-foo': 'bar'}
Jean Vincent
Currently developing ReactiveSets/toubkal, a High-Performances Reactive Web Application Framework under nodejs providing best performances in terms of latency, raw-speed and code size. Toubkal also allows higher code productivity thanks to an concise intuitive API. Check it out on github.
Updated on July 08, 2022Comments
-
Jean Vincent almost 2 years
Is there a clever (i.e. optimized) way to rename a key in a javascript object?
A non-optimized way would be:
o[ new_key ] = o[ old_key ]; delete o[ old_key ];
-
Ivo Wetzel over 13 years@ChaosPandion sorry about that, but I'm really tired of bug ridden JS code, I'm currently writing a Guide (github.com/BonsaiDen/JavaScript-Garden) about all the quirks (including the one you now have fixed), this might have put me into some kind of rant mode ;) (Removed the -1 now)
-
ChaosPandion over 13 years@Ivo - Could you explain why you feel extending the prototype is bad? Prototypes were made for extending baby!
-
Ivo Wetzel over 13 years@ChaosPandion Not the natives one, because they introduce all the mess with
in
etc. Prototype.js is a great example why it is bad, even its developers have admitted that is was a bad thing to use it for the library. -
ChaosPandion over 13 years@Ivo - I agree that it is risky, but there is nothing that will stop me from extending the prototype if I felt it lead to more expressive code. Although I am coming from an ECMAScript 5 mindset where you can mark a property as non-enumerable via
Object.defineProperty
. -
David Tang over 13 years@Ivo - If it is proper practice to always use
hasOwnProperty
to check for properties and withinfor ... in
loops, then why does it matter if we extend Object? -
Jean Vincent over 13 yearsThank you very much for your efforts but the use case does not manipulate static objects as their structure and depth is unkown. So if possible I would like to stick to the original scope of the question.
-
Jean Vincent over 13 years@Box9, it should be standard practice but it is not, especially among "standard" developers.
-
Jean Vincent over 11 yearsThis is a nice ES5-only solution with the real plus of preserving all properties. So this is not "optimized" but definitly more accurate on ES5.
-
Bent Cardan almost 11 yearsupvoted with some skepticism toward writing_things_with_underscores, but of course that was due to the person asking the question. this is the correct response in my view.
-
Scott Stafford almost 10 yearsIn case it matters, I believe this particular usage of ES5 is an IE9-and-newer solution.
-
Brandon Minton almost 10 yearsThis code works but the caveat is that if the new key name already exists, its value is going to get down trodden: jsfiddle.net/ryurage/B7x8x
-
Dex about 9 years@BrandonMinton I came across this too. I've added a simple fix with readability in mind.
-
David Dias almost 9 yearsMade an updated version of your solution that doesn't transform static keys to 'undefined' here: gist.github.com/diasdavid/f8997fb0bdf4dc1c3543 Nevertheless, it still doesn't over the problem of wanting to remap keys at several levels of the JSON object (remaping nested keys), ideas?
-
BlondinkaBrain over 8 yearsooops! var object = {b : '123', 'c' : 'bbb'}; var str = JSON.stringify(object); str = str.replace(/b/g, 'newKey'); str = str.replace(/c/g, 'newKey2'); object = JSON.parse(str);
-
mix3d over 8 yearsHow does this compare for speed?
-
mix3d over 8 yearsAlso runs into a potential issue of somewhere in the datavalues is the same string as the old key name.
-
Jed Fox over 7 yearsPlease use the edit link to explain how this code works and don't just give the code, as an explanation is more likely to help future readers. See also How to Answer. source
-
Tudor Morar over 7 yearsI agree. It does not answer the question specifically but it helped me in getting the job done as a solution for renaming all keys in the object. Maybe I missed the topic..
-
rsp about 7 years"Works perfectly" for certain definitions of "perfectly". Try to rename
'a'
in{ a: 1, aa: 2, aaa: 3}
or try to rename an object with values that are anything more than strings or numbers or booleans, or try with circular references. -
ikhsan almost 7 yearsif the object contains function or date object, this will not work
-
Akin Hwan over 6 yearsthis should be accepted answer, worked great for my use case. I had to convert an API response that was prefixing Country Names with unnecessary string. Turned Object into array of keys and mapped through each key with substring method and returned a new object with new key and value indexed by original key
-
mjarraya about 6 yearsThis truly is a horrendous solution
-
jose about 6 yearsI suggest adding a validation that o.old_key exists. Changing:
if (old_key !== new_key)
to:if (old_key !== new_key && o[old_key])
-
Tim over 5 yearsTry: delete Object.assign(o, {newKey: o.oldKey }).oldKey; Worked well for me
-
Jon Adams over 5 yearsPerhaps you could explain what this is doing and how it works?
-
Soumya Kanti over 5 yearsWhy is there the square brace
[]
aroundnewKey
? The solution works without that actually. -
Soumya Kanti over 5 yearsOk - I got my answer. It's the ES6 feature. For anyone else stumbled on this like me, here is a good answer.
-
lowcrawler about 5 yearsThis answer would be stronger if your variable names were more verbose.
-
lowcrawler almost 5 yearsPerhaps? Sorry, I forget what I was thinking with my initial comment.
-
TomoMiha over 4 yearsThis solution worked for me, but pay attention to always return a 'key' variable. Example: if(key === 'oldKey') { return 'newKey'; } return key;
-
blueprintchris over 4 yearsThis is nice as it doesn't delete the old key. Deleting the old key will remove the key entirely from the object if the key name hasn't changed. In my example, I was converting
my_object_property
tomyObjectProperty
, however, if my property was single-worded, then the key was removed. +1 -
TAHA SULTAN TEMURI over 4 yearsthis is the best solution
-
franco phong about 4 yearsThis is the best solution. But need some understand about spread operator.
-
user3808307 about 4 years@JeffLowery what if it was an array of objects? Do I have to do a foreach or can I do with spread too?
-
Jeff Lowery about 4 years@user3808307 You can do a spread on an array, and objects in the array.
-
Johann about 4 yearsNOTE: The use of Object.assign only does a shallow copy.
-
gignu over 3 yearsThx a lot, I was getting confused by all the other answers. This one is simple and maintains the order. Exactly what I was looking for!
-
desh over 3 yearsi cant seem to understand this part const { [OLD_KEY]: replaceByKey, ...rest } = obj
-
homerThinking over 3 yearsworks fine for rename the key, but the value is lost
-
Dexygen over 3 yearsThis is by far the simplest in my opinion and should be the accepted answer. I used it to lower-case all my keys and substitute spaces with underscores.
-
Devin Rhode over 3 yearsAbsolutely brilliant. Using the first parameter,
oldProp
, for some magical destructing in the 3rd param. -
Krishna over 3 yearsread about destructuring of object. here
-
steviesh over 3 yearsThis only copies the enumerable properties - if you're looking for identical behavior I do not believe this will work.
-
Dror Bar almost 3 yearsWhy use Object.assign instead of using spread operator (...)?
-
Andre Goulart almost 3 yearsI also suggest adding a validation that
o.new_key
already exists, for avoid overwriting. Changing:if (old_key !== new_key && o[old_key])
toif (old_key !== new_key && o[old_key] && !o[new_key])
-
Ruan Mendes over 2 yearsNobody modifies built-in prototypes in 2021. Main reason is not just that it shows up in
for in
loops but because a method could be introduced in the future and this would clash with it. Just make afunction renameProps(obj, oldName, newName){}
so you never have to worry. -
Admin over 2 yearsYour answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
-
L.Dutch over 2 yearsThis does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From Review
-
aderchox over 2 yearsIt first creates the new key, then merges it into the object, then deletes the old key from the merged object. Nice solution.
-
ya_dimon about 2 years
const changedKey
should beconst valueOfChangedKey
. And does not work, if the key is in the middle of object. + You need the cloneDeep function. So not that good solution :) -
Raqha about 2 yearsNice, this suites my use case perfeclty
-
Valeriu Paloş about 2 yearsNormally I would agree with you, but in this case I think it's clear enough, otherwise nobody would have understood the question (which uses
o
). -
user3342816 about 2 years@BentCardan Hah. I always use underscores. One thing is that it clearly distinguish multi-word properties from native JS i.e.
foo.get_key()
and in general I find it easier to read which is the ultimate goal anyhow..