替換json對(duì)象中的key最佳方案
JSON(JavaScript Object Notation, JS 對(duì)象簡(jiǎn)譜) 是一種輕量級(jí)的數(shù)據(jù)交換格式。它基于 ECMAScript (歐洲計(jì)算機(jī)協(xié)會(huì)制定的js規(guī)范)的一個(gè)子集,采用完全獨(dú)立于編程語言的文本格式來存儲(chǔ)和表示數(shù)據(jù)。簡(jiǎn)潔和清晰的層次結(jié)構(gòu)使得 JSON 成為理想的數(shù)據(jù)交換語言。 易于人閱讀和編寫,同時(shí)也易于機(jī)器解析和生成,并有效地提升網(wǎng)絡(luò)傳輸效率。
看到標(biāo)題你可能會(huì)想,如此簡(jiǎn)單的問題值得去探究嗎?如果我有一個(gè)json object,只需下面簡(jiǎn)單的幾行代碼就可以完成:
var obj = {
"_id": "5078c3a803ff4197dc81fbfb",
"email": "user1@gmail.com",
"image": "some_image_url",
"name": "Name 1"
};
var new_key = "id";
var old_key = "_id";
obj[new_key] = obj[old_key];
delete obj[old_key];
是的,沒錯(cuò)!以上代碼可以很好地完成工作,從而將obj對(duì)象中的"_id"替換成"id"。
在大多數(shù)情況下,這種方式不會(huì)帶來什么問題,但是,如果你需要將obj對(duì)象序列化到文檔中并比較差異,你就會(huì)看到問題。
// 修改之前的obj
{
"_id": "5078c3a803ff4197dc81fbfb",
"email": "user1@gmail.com",
"image": "some_image_url",
"name": "Name 1"
}
// 修改之后的obj
// JSON.stringify(obj, null, "\t")
{
"email": "user1@gmail.com",
"image": "some_image_url",
"name": "Name 1",
"id": "5078c3a803ff4197dc81fbfb"
}
新添加的key默認(rèn)放在了最后,并且由于在替換過程中我們刪除了之前的key,所以導(dǎo)致序列化之后的obj與之前的obj存在較大的差異。

那如何才能保證在最小差異的情況下實(shí)現(xiàn)key的替換呢?下面是我找到的一些方法:
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;
};
function renameKeys(obj, newKeys) {
const keyValues = Object.keys(obj).map(key => {
const newKey = newKeys[key] || key;
return { [newKey]: obj[key] };
});
return Object.assign({}, ...keyValues);
}
const obj = { a: "1", b: "2" };
const newKeys = { a: "A", c: "C" };
const renamedObj = renameKeys(obj, newKeys);
console.log(renamedObj);
// {A:"1", b:"2"}
// 使用lodash的_.mapKeys()函數(shù)
var user = {
name: "Andrew",
id: 25,
reported: false
};
var renamed = _.mapKeys(user, function(value, key) {
return key + "_" + user.id;
});
console.log(renamed);
var str = JSON.stringify(object); str = str.replace(/oldKey/g, 'newKey'); str = str.replace(/oldKey2/g, 'newKey2'); object = JSON.parse(str);
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;
}
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);
上面這些例子有一部分可以達(dá)到我們的要求,另外有一部分和本文開頭給出的代碼基本等效(只是在執(zhí)行效率上略有差別)。但所有這些示例無一例外都不能同時(shí)滿足下面兩個(gè)要需:
保留要替換的key在原json對(duì)象中的順序。既保證在JSON.stringify()執(zhí)行之后輸出的字符串中key的順序和原json對(duì)象是一致的。在原json對(duì)象上進(jìn)行修改,而不是返回一個(gè)新的json對(duì)象。某些情況下,我們需要對(duì)一個(gè)復(fù)雜json對(duì)象的子元素進(jìn)行修改,如果修改之后返回一個(gè)新的json對(duì)象,則無法保證這個(gè)新的對(duì)象會(huì)反應(yīng)到原json對(duì)象中。例如,jspath是一個(gè)可以通過domain-specific language (DSL)在給定的json對(duì)象中查找子元素的javascript庫(kù),通過下面的代碼我們可以輕易地查找出obj對(duì)象中automobiles屬性中maker === "Honda"并且year > 2009的元素。
var obj = {
"automobiles" : [
{ "maker" : "Nissan", "model" : "Teana", "year" : 2011 },
{ "maker" : "Honda", "model" : "Jazz", "year" : 2010 },
{ "maker" : "Honda", "model" : "Civic", "year" : 2007 },
{ "maker" : "Toyota", "model" : "Yaris", "year" : 2008 },
{ "maker" : "Honda", "model" : "Accord", "year" : 2011 }
],
"motorcycles" : [{ "maker" : "Honda", "model" : "ST1300", "year" : 2012 }]
};
var res = JSPath.apply('.automobiles{.maker === "Honda" && .year > 2009}', obj);
// res: [{ "maker" : "Honda", "model" : "Jazz", "year" : 2010 }, { "maker" : "Honda", "model" : "Accord", "year" : 2011 }]
注意這里返回的res對(duì)象是obj對(duì)象的一部分,意味著后續(xù)對(duì)res對(duì)象所做的任何修改都會(huì)反應(yīng)到obj對(duì)象中。如果我們對(duì)res中的某些key進(jìn)行替換,而返回一個(gè)新json對(duì)象的話,那么這個(gè)修改就不會(huì)反應(yīng)到obj對(duì)象中。
基本思路:既然新添加的key默認(rèn)都會(huì)排在最后,那么索性遍歷json對(duì)象的所有key,然后將key一一替換為一個(gè)臨時(shí)名稱,隨后再將這個(gè)臨時(shí)名稱替換回來。在這個(gè)過程中,如果遇到真正需要替換的key,則不再進(jìn)行二次替換。下面是具體的代碼:
var obj = {
"_id": "5078c3a803ff4197dc81fbfb",
"email": "user1@gmail.com",
"image": "some_image_url",
"name": "Name 1"
};
var new_key = "id";
var old_key = "_id";
Object.keys(obj).forEach(key => {
if (key === old_key) {
obj[new_key] = obj[key];
delete obj[key];
} else {
obj[`_${key}`] = obj[key];
delete obj[key];
obj[`${key}`] = obj[`_${key}`];
delete obj[`_${key}`];
}
});
完成之后的效果如下圖:

當(dāng)然,如果考慮通用性,可能需要遞歸遍歷給定的json對(duì)象。以上代碼只是給出了一個(gè)思路,考慮到執(zhí)行效率和安全性,這個(gè)并不是最佳方案,真實(shí)使用中我們可以逐步進(jìn)行完善。
以上就是替換json對(duì)象中的key最佳方案的詳細(xì)內(nèi)容,更多關(guān)于替換json對(duì)象中的key的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
如何讓動(dòng)態(tài)插入的javascript腳本代碼跑起來。
如何讓動(dòng)態(tài)插入的javascript腳本代碼跑起來。...2007-01-01
淺談JavaScript事件綁定的常用方法及其優(yōu)缺點(diǎn)分析
下面小編就為大家?guī)硪黄獪\談JavaScript事件綁定的常用方法及其優(yōu)缺點(diǎn)分析。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-11-11
JS一維數(shù)組轉(zhuǎn)化為三維數(shù)組的實(shí)現(xiàn)示例
很多時(shí)候,跟后端接口開發(fā)對(duì)接時(shí),因?yàn)樾枨蟮年P(guān)系,需要前端地區(qū)數(shù)據(jù)跟后端的數(shù)據(jù)要一一對(duì)應(yīng),有時(shí)候需要的是多維數(shù)據(jù),這篇文章主要介紹了JS一維數(shù)組轉(zhuǎn)化為三維數(shù)組的實(shí)現(xiàn)示例,感興趣的可以了解一下2021-12-12
javascript實(shí)現(xiàn)時(shí)間格式輸出FormatDate函數(shù)
這篇文章主要介紹了javascript實(shí)現(xiàn)時(shí)間格式輸出FormatDate函數(shù),可實(shí)現(xiàn)fmt標(biāo)簽一樣對(duì)日期時(shí)間型內(nèi)容格式輸入的功能,是非常實(shí)用的技巧,需要的朋友可以參考下2015-01-01
ES6中數(shù)組array新增方法實(shí)例總結(jié)
這篇文章主要介紹了ES6中數(shù)組array新增方法,結(jié)合實(shí)例形式總結(jié)分析了ES6中數(shù)組array各種新增方法的功能及使用技巧,需要的朋友可以參考下2017-11-11
echarts中tooltip添加點(diǎn)擊事件代碼示例
這篇文章主要給大家介紹了關(guān)于echarts中tooltip添加點(diǎn)擊事件的相關(guān)資料,echarts tooltip點(diǎn)擊事件是指當(dāng)用戶點(diǎn)擊圖表中的提示框(tooltip)時(shí)觸發(fā)的事件,需要的朋友可以參考下2023-07-07
javascript實(shí)現(xiàn)的一個(gè)自定義長(zhǎng)度的文本自動(dòng)換行的函數(shù)。
javascript實(shí)現(xiàn)的一個(gè)自定義長(zhǎng)度的文本自動(dòng)換行的函數(shù)。...2007-08-08

