经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » JavaScript » 查看文章
如何替换json对象中的key
来源:cnblogs  作者:Jaxu  时间:2021/6/7 9:12:05  对本文有异议

  看到标题你可能会想,如此简单的问题值得去探究吗?如果我有一个json object,只需下面简单的几行代码就可以完成:

  1. var obj = {
  2. "_id": "5078c3a803ff4197dc81fbfb",
  3. "email": "user1@gmail.com",
  4. "image": "some_image_url",
  5. "name": "Name 1"
  6. };
  7. var new_key = "id";
  8. var old_key = "_id";
  9. obj[new_key] = obj[old_key];
  10. delete obj[old_key];

  是的,没错!以上代码可以很好地完成工作,从而将obj对象中的"_id"替换成"id"。

  在大多数情况下,这种方式不会带来什么问题,但是,如果你需要将obj对象序列化到文档中并比较差异,你就会看到问题。

  1. // 修改之前的obj
  2. {
  3. "_id": "5078c3a803ff4197dc81fbfb",
  4. "email": "user1@gmail.com",
  5. "image": "some_image_url",
  6. "name": "Name 1"
  7. }
  8. // 修改之后的obj
  9. // JSON.stringify(obj, null, "\t")
  10. {
  11. "email": "user1@gmail.com",
  12. "image": "some_image_url",
  13. "name": "Name 1",
  14. "id": "5078c3a803ff4197dc81fbfb"
  15. }

  新添加的key默认放在了最后,并且由于在替换过程中我们删除了之前的key,所以导致序列化之后的obj与之前的obj存在较大的差异。

  那如何才能保证在最小差异的情况下实现key的替换呢?下面是我找到的一些方法:

  1. Object.prototype.renameProperty = function (oldName, newName) {
  2. // Do nothing if the names are the same
  3. if (oldName === newName) {
  4. return this;
  5. }
  6. // Check for the old property name to avoid a ReferenceError in strict mode.
  7. if (this.hasOwnProperty(oldName)) {
  8. this[newName] = this[oldName];
  9. delete this[oldName];
  10. }
  11. return this;
  12. };

 

  1. function renameKeys(obj, newKeys) {
  2. const keyValues = Object.keys(obj).map(key => {
  3. const newKey = newKeys[key] || key;
  4. return { [newKey]: obj[key] };
  5. });
  6. return Object.assign({}, ...keyValues);
  7. }
  8. const obj = { a: "1", b: "2" };
  9. const newKeys = { a: "A", c: "C" };
  10. const renamedObj = renameKeys(obj, newKeys);
  11. console.log(renamedObj);
  12. // {A:"1", b:"2"}

 

  1. // 使用lodash的_.mapKeys()函数
  2. var user = {
  3. name: "Andrew",
  4. id: 25,
  5. reported: false
  6. };
  7. var renamed = _.mapKeys(user, function(value, key) {
  8. return key + "_" + user.id;
  9. });
  10. console.log(renamed);

 

  1. var str = JSON.stringify(object);
  2. str = str.replace(/oldKey/g, 'newKey');
  3. str = str.replace(/oldKey2/g, 'newKey2');
  4. object = JSON.parse(str);

 

  1. function renameObjectKey(oldObj, oldName, newName) {
  2. const newObj = {};
  3. Object.keys(oldObj).forEach(key => {
  4. const value = oldObj[key];
  5. if (key === oldName) {
  6. newObj[newName] = value;
  7. } else {
  8. newObj[key] = value;
  9. }
  10. });
  11. return newObj;
  12. }

 

  1. data = {key1: "value1", key2: "value2", key3: "value3"};
  2. keyMap = {key1: "firstkey", key2: "secondkey", key3: "thirdkey"};
  3. mappedData = Object.keys(keyMap).reduce((obj,k) => Object.assign(obj, { [keyMap[k]]: data[k] }),{});
  4. console.log(mappedData);

  上面这些例子有一部分可以达到我们的要求,另外有一部分和本文开头给出的代码基本等效(只是在执行效率上略有差别)。但所有这些示例无一例外都不能同时满足下面两个要需:

  1. 保留要替换的key在原json对象中的顺序。既保证在JSON.stringify()执行之后输出的字符串中key的顺序和原json对象是一致的。
  2. 在原json对象上进行修改,而不是返回一个新的json对象。某些情况下,我们需要对一个复杂json对象的子元素进行修改,如果修改之后返回一个新的json对象,则无法保证这个新的对象会反应到原json对象中。例如,jspath是一个可以通过domain-specific language (DSL)在给定的json对象中查找子元素的javascript库,通过下面的代码我们可以轻易地查找出obj对象中automobiles属性中maker === "Honda"并且year > 2009的元素。
  1. var obj = {
  2. "automobiles" : [
  3. { "maker" : "Nissan", "model" : "Teana", "year" : 2011 },
  4. { "maker" : "Honda", "model" : "Jazz", "year" : 2010 },
  5. { "maker" : "Honda", "model" : "Civic", "year" : 2007 },
  6. { "maker" : "Toyota", "model" : "Yaris", "year" : 2008 },
  7. { "maker" : "Honda", "model" : "Accord", "year" : 2011 }
  8. ],
  9. "motorcycles" : [{ "maker" : "Honda", "model" : "ST1300", "year" : 2012 }]
  10. };
  11. var res = JSPath.apply('.automobiles{.maker === "Honda" && .year > 2009}', obj);
  12. // res: [{ "maker" : "Honda", "model" : "Jazz", "year" : 2010 }, { "maker" : "Honda", "model" : "Accord", "year" : 2011 }]

  注意这里返回的res对象是obj对象的一部分,意味着后续对res对象所做的任何修改都会反应到obj对象中。如果我们对res中的某些key进行替换,而返回一个新json对象的话,那么这个修改就不会反应到obj对象中。

  基本思路:既然新添加的key默认都会排在最后,那么索性遍历json对象的所有key,然后将key一一替换为一个临时名称,随后再将这个临时名称替换回来。在这个过程中,如果遇到真正需要替换的key,则不再进行二次替换。下面是具体的代码:

  1. var obj = {
  2. "_id": "5078c3a803ff4197dc81fbfb",
  3. "email": "user1@gmail.com",
  4. "image": "some_image_url",
  5. "name": "Name 1"
  6. };
  7. var new_key = "id";
  8. var old_key = "_id";
  9. Object.keys(obj).forEach(key => {
  10. if (key === old_key) {
  11. obj[new_key] = obj[key];
  12. delete obj[key];
  13. } else {
  14. obj[`_${key}`] = obj[key];
  15. delete obj[key];
  16. obj[`${key}`] = obj[`_${key}`];
  17. delete obj[`_${key}`];
  18. }
  19. });

  完成之后的效果如下图:

  当然,如果考虑通用性,可能需要递归遍历给定的json对象。以上代码只是给出了一个思路,考虑到执行效率和安全性,这个并不是最佳方案,真实使用中我们可以逐步进行完善。

原文链接:http://www.cnblogs.com/jaxu/p/14836088.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号