替換json物件中的key最佳方案
jsON(javascript Object Notation,JS 物件簡譜) 是一種輕量級的資料交換格式。它基於 ECMAScript (歐洲計算機協會制定的js規範)的一個子集,採用完全獨立於程式設計語言的文字格式來儲存和表示資料。簡潔和清晰的層次結構使得 Jwww.cppcns.comSON 成為理想的資料交換語言。 易於人閱讀和編寫,同時也易於機器解析和生成,並有效地提升網路傳輸效率。
看到標題你可能會想,如此簡單的問題值得去探究嗎?如果我有一個json object,只需下面簡單的幾行程式碼就可以完成:
var obj = { "_id": "5078c3a803ff4197dc81fbfb","email": "[email protected]","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];
是的,沒錯!以上程式碼可以很好地完成工作,從而將obj物件中的"_id"替換成"id"。
在大多數情況下,這種方式不會帶來什麼問題,但是,如果你需要將obj物件序列化到文件中並比較差異,你就會看到問題。
// 修改之前的obj { "_id": "5078c3a803ff4197dc81fbfb","name": "Name 1" } // 修改之後的obj // JSON.stringify(obj,null,"\t") { "email": "[email protected]","name": "Name 1","id": "5078c3a803ff4197dc81fbfb" }
新新增的key預設放在了最後,並且由於在替換過程中我們刪除了之前的key,所以導致序列化之後的obj與之前的obj存在較大的差異。
那如何才能保證在最小差異的情況下實現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()函式 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: "firsthttp://www.cppcns.comkey",key2: "secondkey",key3: "thirdkey"}; mappedData = Object.keys(keyMap).reduce((obj,k) => Object.assign(obj,{ [keyMap[k]]: data[k] }),{}); console.log(mappedData);
上面這些例子有一部分可以達到我們的要求,另外有一部分和本文開頭給出的程式碼基本等效(只是在執行效率上略有差別)。但所有這些示例無一例外都不能同時滿足下面兩個要需:
保留要替換的key在原json物件中的順序。既保證在JSON.stringify()執行之後輸出的字串中key的順序和原json物件是一致的。在原json物件上進行修改,而不是返回一個新的json物件。某些情況下,我們需要對一個複雜json物件的子元素進行修改,如果修改之後返回一個新的json物件,則無法保證這個新的物件會反應到原json物件中。例如,jspath是一個可以通過domain-specific language (DSL)在給定的json物件中查詢子元素的javascript庫,通過下面的程式碼我們可以輕易地查找出obj物件中automobiles屬性中maker === "Honda"並且year > 2009的元素。
var obj = {
"automobiles" : [
{ "maker" : "Nissan","model" : "Teana","year" : 2011 },{ "maker" : "Honda","model" : "Jazz","year" : 2010 },"model" : "Civic","year" : 2007 },{ "maker" : "Toyota","model" : "Yaris","year" : 2008 },"model" : "Accord","year" : 2011 }
],"motorcycles" : [{ "maker" : "Honda","model" : "ST1300","year" : 2012http://www.cppcns.com }]
};
var res = JSPath.apply('.automobiles{.maker === "Honda" && .year > 2009}',obj);
// res: [{ "maker" : "Honda","model" : "jJjQQtdTTJazz","year" : 2011 }]
注意這裡返回的res物件是obj物件的一部分,意味著後續對res物件所做的任何修改都會反應到obj物件中。如果我們對res中的某些key進行替換,而返回一個新json物件的話,那麼這個修改就不會反應到obj物件中。
基本思路:既然新新增的key預設都會排在最後,那麼索性遍歷json物件的所有key,然後將key一一替換為一個臨時名稱,隨後再將這個臨時名稱替換回來。在這個過程中,如果遇到真正需要替換的key,則不再進行二次替換。下面是具體的程式碼:
var obj = { "_id": "5078c3a803ff4197dc81fbfb","email": "[email protected]www.cppcns.com","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}`]; } });
完成之後的效果如下圖:
當然,如果考慮通用性,可能需要遞迴遍歷給定的json物件。以上程式碼只是給出了一個思路,考慮到執行效率和安全性,這個並不是最佳方案,真實使用中我們可以逐步進行完善。
以上就是替換json物件中的key最佳方案的詳細內容,更多關於替換json物件中的key的資料請關注我們其它相關文章!