如何替换json对象中的key

更新日期: 2021-06-03阅读: 2k标签: json

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

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];

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

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

// 修改之前的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默认放在了最后,并且由于在替换过程中我们删除了之前的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: "firstkey", 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 },
        { "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对象是obj对象的一部分,意味着后续对res对象所做的任何修改都会反应到obj对象中。如果我们对res中的某些key进行替换,而返回一个新json对象的话,那么这个修改就不会反应到obj对象中。

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

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}`];
    }
});
完成之后的效果如下图:


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

来自:https://www.cnblogs.com/jaxu/archive/2021/06/01/14836088.html


链接: https://fly63.com/article/detial/10384

web数据格式中关于:XML/HTML/JSON学习总汇

这篇文章讲解关于XML/HTML/JSON的学习,大家都知道服务器端可以返回的数据格式,主要就是:XML、HTML、JSON,当我们做数据抓取,ajax请求的时候都需要熟悉它们的使用。

解决IE8下JSON.stringify()自动将中文转译成unicode的方法

在IE8下JSON.stringify()自动将中文转译为unicode编码,原本选择的中文字符,传到后台变为了unicode编码,即u****的形式。查找资料后发现,与标准的JSON.stringify()不同,IE8内置的JSON.stringify()会自动将编码从utf-8转为unicode编码,导致出现这种类似于乱码的情况。

js实现json格式化,以及json校验工具的简单实现

这篇文章主要讲解:json结构及形式、json字符串转化为json对象【通过eval( ) 方法,new Function形式,使用全局的JSON对象】、json校验格式化工具简单实现

解析Json字符串的三种方法

在很多时候,我们的需要将类似 json 格式的字符串数据转为json,下面将介绍日常中使用的三种解析json字符串的方法

解决IE8以下低版本实现JSON.parse()与JSON.stringify()的兼容

将字符串和json对象的相互转换,我们通常使用JSON.parse()与JSON.stringify()。解决IE8以下低版本实现JSON.parse()与JSON.stringify()的兼容呢:利用eval方式解析、new Function形式、自定义兼容json的方法、head头添加mate等

什么是数据交互格式?xml和json优缺点

就是客户端和服务端进行信息传输的格式(xml和json),双方约定用什么格式进行传输,然后解析得到自己想要的值,xml扩展标记语言,属于重量级(第一占宽带、第二解析难),json属于轻量级的数据交互格式(不占宽带,解析很简单)

js 将json字符串转换为json对象的方法解析

将json字符串转换为json对象的方法。在数据传输过程中,json是以文本,即字符串的形式传递的,而JS操作的是JSON对象,所以,JSON对象和JSON字符串之间的相互转换是关键

聊聊JSON Schema

json现在已经成为比较通用灵活的数据交换格式,尤其是在web方面,总是少不了它的身影,js原生就支持它。网页中与服务器中和服务器交换信息也基本上式基于json的。在现在的开发中,特别是在前后端分离的开发中,后端提供接口,前端通过接口拿取数据;

百度JSON LD结构化数据代码分享

百度JSON LD结构化数据代码分享,搞外贸网站,企业网站这么就,对谷歌的 schema 结构化数据比较熟悉,但是对百度的结构化数据就了解太少了

什么是JWT(JSON WEB TOKEN)

Json web token(JWT)是为了网络应用环境间传递声明而执行的一种基于JSON的开发标准(RFC 7519),该token被设计为紧凑且安全的,特别适用于分布式站点的单点登陆(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!