¿Hay alguna forma inteligente (es decir, optimizada) de cambiar el nombre de una clave en un objeto javascript?
Una forma no optimizada sería:
o[ new_key ] = o[ old_key ];
delete o[ old_key ];
¿Hay alguna forma inteligente (es decir, optimizada) de cambiar el nombre de una clave en un objeto javascript?
Una forma no optimizada sería:
o[ new_key ] = o[ old_key ];
delete o[ old_key ];
Respuestas:
Creo que la forma más completa (y correcta) de hacerlo sería:
if (old_key !== new_key) {
Object.defineProperty(o, new_key,
Object.getOwnPropertyDescriptor(o, old_key));
delete o[old_key];
}
Este método asegura que la propiedad renombrada se comporte de manera idéntica a la original.
Además, me parece que la posibilidad de envolver esto en una función / método y ponerlo Object.prototype
es irrelevante con respecto a su pregunta.
if (old_key !== new_key)
a: if (old_key !== new_key && o[old_key])
Puede ajustar el trabajo en una función y asignarlo al Object
prototipo. Tal vez use el estilo de interfaz fluido para hacer fluir múltiples cambios de nombre.
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 específico
Desearía que la sintaxis no fuera tan compleja, pero definitivamente es bueno tener más 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;
}
}
);
Object.defineProperty
.
hasOwnProperty
para verificar las propiedades y dentro de los for ... in
bucles, entonces ¿por qué importa si ampliamos Object?
Si está mutando su objeto fuente, ES6 puede hacerlo en una línea.
delete Object.assign(o, {[newKey]: o[oldKey] })[oldKey];
O dos líneas si desea crear un nuevo objeto.
const newObject = {};
delete Object.assign(newObject, o, {[newKey]: o[oldKey] })[oldKey];
[]
alrededor newKey
? La solución funciona sin eso en realidad.
En caso de que alguien necesite cambiar el nombre de una lista de propiedades:
function renameKeys(obj, newKeys) {
const keyValues = Object.keys(obj).map(key => {
const newKey = newKeys[key] || key;
return { [newKey]: obj[key] };
});
return Object.assign({}, ...keyValues);
}
Uso:
const obj = { a: "1", b: "2" };
const newKeys = { a: "A", c: "C" };
const renamedObj = renameKeys(obj, newKeys);
console.log(renamedObj);
// {A:"1", b:"2"}
my_object_property
a myObjectProperty
, sin embargo, si mi propiedad era de una sola palabra, entonces la clave fue eliminada. +1
ES6(ES2015)
camino!¡Necesitamos mantenernos al día!
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"}
Si no desea mutar sus datos, considere esta función ...
renameProp = (oldProp, newProp, {[oldProp]:old, ...others}) => ({
[newProp]: old,
...others
})
Una explicación detallada de Yazeed Bzadough https://medium.com/front-end-hacking/immutably-rename-object-keys-in-javascript-5f6353c7b6dd
La mayoría de las respuestas aquí no logran mantener el orden de pares clave-valor del objeto JS. Si tiene una forma de pares de clave-valor de objeto en la pantalla que desea modificar, por ejemplo, es importante preservar el orden de las entradas de objeto.
La forma ES6 de recorrer el objeto JS y reemplazar el par clave-valor con el nuevo par con un nombre clave modificado sería algo así como:
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 solución conserva el orden de las entradas al agregar la nueva entrada en lugar de la anterior.
Puedes probar 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>
Una variación usando el operador de desestructuración y propagación de objetos:
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 the renamed properties kA, kB, kC;
// spread the remaining original properties in the 'rest' variable
const newObj = {kA, kB, kC, ...rest};
Personalmente, la forma más efectiva de cambiar el nombre de las claves en el objeto sin implementar complementos y ruedas extra pesados:
var str = JSON.stringify(object);
str = str.replace(/oldKey/g, 'newKey');
str = str.replace(/oldKey2/g, 'newKey2');
object = JSON.parse(str);
También puede envolverlo try-catch
si su objeto tiene una estructura no válida. Funciona perfectamente :)
'a'
de { a: 1, aa: 2, aaa: 3}
o tratar de cambiar el nombre de un objeto con valores que son algo más que cadenas o números o booleanos, o tratar con referencias circulares.
Haría algo como esto:
function renameKeys(dict, keyMap) {
return _.reduce(dict, function(newDict, val, oldKey) {
var newKey = keyMap[oldKey] || oldKey
newDict[newKey] = val
return newDict
}, {})
}
Diría que sería mejor desde un punto de vista conceptual simplemente dejar el objeto antiguo (el del servicio web) como está, y poner los valores que necesita en un objeto nuevo. Supongo que está extrayendo campos específicos en un punto u otro de todos modos, si no en el cliente, al menos en el servidor. El hecho de que elija usar nombres de campo que sean los mismos que los del servicio web, solo en minúsculas, realmente no cambia esto. Entonces, aconsejaría hacer algo como esto:
var myObj = {
field1: theirObj.FIELD1,
field2: theirObj.FIELD2,
(etc)
}
Por supuesto, estoy haciendo todo tipo de suposiciones aquí, lo que puede no ser cierto. Si esto no se aplica a usted, o si es demasiado lento (¿no es así? No lo he probado, pero imagino que la diferencia se reduce a medida que aumenta el número de campos), ignore todo esto :)
Si no desea hacer esto, y solo tiene que admitir navegadores específicos, también puede usar los nuevos captadores para devolver también "mayúsculas (campo)": consulte http://robertnyman.com/2009/05/28 / getters-and-setters-with-javascript-code-samples-and-demos / y los enlaces en esa página para obtener más información.
EDITAR:
Increíblemente, esto también es casi el doble de rápido, al menos en mi FF3.5 en el trabajo. Ver: http://jsperf.com/spiny001
Si bien esto no proporciona exactamente una mejor solución para cambiar el nombre de una clave, proporciona una forma ES6 rápida y fácil de cambiar el nombre de todas las claves en un objeto sin mutar los datos que contienen.
let b = {a: ["1"], b:["2"]};
Object.keys(b).map(id => {
b[`root_${id}`] = [...b[id]];
delete b[id];
});
console.log(b);
Algunas de las soluciones enumeradas en esta página tienen algunos efectos secundarios:
Aquí hay una solución que mantiene la posición de la clave en el mismo lugar y es compatible con IE9 +, pero tiene que crear un nuevo objeto y puede no ser la solución más rápida:
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;
}
Tenga en cuenta: IE9 puede no ser compatible con cada uno en modo estricto
Otra forma más con el método REDUCE más poderoso .
data = {key1: "value1", key2: "value2", key3: "value3"};
keyMap = {key1: "firstkey", key2: "secondkey", key3: "thirdkey"};
mappedData = Object.keys(keyMap).reduce((obj,k) => Object.assign(obj, { [keyMap[k]]: data[k] }),{});
console.log(mappedData);
Esta es una pequeña modificación que hice a la función de pomber; Para poder tomar una matriz de objetos en lugar de un objeto solo y también puede activar el índice. También las "claves" pueden ser asignadas por una matriz
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;
}
prueba
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);
Tu camino está optimizado, en mi opinión. Pero terminarás con las claves reordenadas. La clave recién creada se agregará al final. Sé que nunca debe confiar en el orden de las claves, pero si necesita preservarlo, deberá revisar todas las claves y construir un nuevo objeto uno por uno, reemplazando la clave en cuestión durante ese proceso.
Me gusta esto:
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;
npm i paix
import { paix } from 'paix';
const source_object = { FirstName: "Jhon", LastName: "Doe", Ignored: true };
const replacement = { FirstName: 'first_name', LastName: 'last_name' };
const modified_object = paix(source_object, replacement);
console.log(modified_object);
// { Ignored: true, first_name: 'Jhon', last_name: 'Doe' };