将返回的JSON对象属性转换为(较低的第一个)camelCase

我从这样的API返回JSON:

Contacts: [{ GivenName: "Matt", FamilyName:"Berry" }] 

为了保持这与我的代码样式(camelCase – 小写首字母)一致,我想转换数组以产生以下内容:

  contacts: [{ givenName: "Matt", familyName:"Berry" }] 

什么是最简单/最好的方法? 创建一个新的Contact对象并迭代返回的数组中的所有联系人?

 var jsonContacts = json["Contacts"], contacts= []; _.each(jsonContacts , function(item){ var contact = new Contact( item.GivenName, item.FamilyName ); contacts.push(contact); }); 

或者我可以映射原始或以某种方式转换它?

这是一个可靠的递归函数,可以正确地获取所有JavaScript对象的属性:

 function toCamel(o) { var newO, origKey, newKey, value if (o instanceof Array) { return o.map(function(value) { if (typeof value === "object") { value = toCamel(value) } return value }) } else { newO = {} for (origKey in o) { if (o.hasOwnProperty(origKey)) { newKey = (origKey.charAt(0).toLowerCase() + origKey.slice(1) || origKey).toString() value = o[origKey] if (value instanceof Array || (value !== null && value.constructor === Object)) { value = toCamel(value) } newO[newKey] = value } } } return newO } 

测试:

 var obj = { 'FirstName': 'John', 'LastName': 'Smith', 'BirthDate': new Date(), 'ArrayTest': ['one', 'TWO', 3], 'ThisKey': { 'This-Sub-Key': 42 } } console.log(JSON.stringify(toCamel(obj))) 

输出:

 { "firstName":"John", "lastName":"Smith", "birthDate":"2017-02-13T19:02:09.708Z", "arrayTest": [ "one", "TWO", 3 ], "thisKey":{ "this-Sub-Key":42 } } 

如果你使用lodash而不是下划线,这将做:

 _.mapKeys(obj, (v, k) => _.camelCase(k)) 

这会将TitleCasesnake_case转换为camelCase 。 请注意,它不是递归的。

要将普通对象的键从snake_casecamelCase 递归尝试以下操作
(使用Lodash ):

 function objectKeysToCamelCase(snake_case_object) { var camelCaseObject = {}; _.forEach( snake_case_object, function(value, key) { if (_.isPlainObject(value) || _.isArray(value)) { // checks that a value is a plain object or an array - for recursive key conversion value = objectKeysToCamelCase(value); // recursively update keys of any values that are also objects } camelCaseObject[_.camelCase(key)] = value; } ) return camelCaseObject; }; 

在这个PLUNKER中测试

注意 :对于数组中的对象也可以递归地工作

好吧,我接受了挑战,并认为我弄清楚了:

 var firstToLower = function(str) { return str.charAt(0).toLowerCase() + str.slice(1); }; var firstToUpper = function(str) { return str.charAt(0).toUpperCase() + str.slice(1); }; var mapToJsObject = function(o) { var r = {}; $.map(o, function(item, index) { r[firstToLower(index)] = o[index]; }); return r; }; var mapFromJsObject = function(o) { var r = {}; $.map(o, function(item, index) { r[firstToUpper(index)] = o[index]; }); return r; }; // Map to var contacts = [ { GivenName: "Matt", FamilyName: "Berry" }, { GivenName: "Josh", FamilyName: "Berry" }, { GivenName: "Thomas", FamilyName: "Berry" } ]; var mappedContacts = []; $.map(contacts, function(item) { var m = mapToJsObject(item); mappedContacts.push(m); }); alert(mappedContacts[0].givenName); // Map from var unmappedContacts = []; $.map(mappedContacts, function(item) { var m = mapFromJsObject(item); unmappedContacts.push(m); }); alert(unmappedContacts[0].GivenName); 

属性转换器(jsfiddle)

诀窍是将对象作为对象属性数组处理。

使用lodash和ES6,这将以递归方式替换所有密钥到camelcase:

速记:

 const camelCaseKeys = (obj) => ((!_.isObject(obj) && obj) || (_.isArray(obj) && obj.map((v) => camelCaseKeys(v))) || _.reduce(obj, (r, v, k) => ({ ...r, [_.camelCase(k)]: camelCaseKeys(v) }), {})); 

扩展:

 const camelCaseKeys = (obj) => { if (!_.isObject(obj)) { return obj; } else if (_.isArray(obj)) { return obj.map((v) => camelCaseKeys(v)); } return _.reduce(obj, (r, v, k) => { return { ...r, [_.camelCase(k)]: camelCaseKeys(v) }; }, {}); }; 

这是axios拦截器的一个很好的用例

基本上,定义客户端类并附加转换请求/响应数据的前/后拦截器。

 export default class Client { get(url, data, successCB, catchCB) { return this._perform('get', url, data, successCB, catchCB); } post(url, data, successCB, catchCB) { return this._perform('post', url, data, successCB, catchCB); } _perform(method, url, data, successCB, catchCB) { // https://github.com/axios/axios#interceptors // Add a response interceptor axios.interceptors.response.use((response) => { response.data = toCamelCase(response.data); return response; }, (error) => { error.data = toCamelCase(error.data); return Promise.reject(error); }); // Add a request interceptor axios.interceptors.request.use((config) => { config.data = toSnakeCase(config.data); return config; }, (error) => { return Promise.reject(error); }); return axios({ method: method, url: API_URL + url, data: data, headers: { 'Content-Type': 'application/json', }, }).then(successCB).catch(catchCB) } } 

这是使用React / axios的更长示例的要点 。

谢谢其他我这样做(使用lodash和ES6的递归函数):

 import { camelCase } from 'lodash'; const camelizeKeys = (obj) => { if (Array.isArray(obj)) { return obj.map(v => camelizeKeys(v)); } else if (obj !== null && obj.constructor === Object) { return Object.keys(obj).reduce( (result, key) => ({ ...result, [camelCase(key)]: camelizeKeys(obj[key]), }), {}, ); } return obj; }; 

测试:

 const obj = { 'FirstName': 'John', 'LastName': 'Smith', 'BirthDate': new Date(), 'ArrayTest': ['one', 'TWO', 3], 'ThisKey': { 'This-Sub-Key': 42 } } console.log(JSON.stringify(camelizeKeys(obj))) 

输出:

 { "firstName": "John", "lastName": "Smith", "birthDate": "2018-05-31T09:03:57.844Z", "arrayTest":[ "one", "TWO", 3 ], "thisKey":{ "thisSubKey": 42 } } 

我需要一个接受数组或对象的generics方法。 这就是我正在使用的(我借用了KyorCode的firstToLower()实现):

 function convertKeysToCamelCase(obj) { if (!obj || typeof obj !== "object") return null; if (obj instanceof Array) { return $.map(obj, function(value) { return convertKeysToCamelCase(value); }); } var newObj = {}; $.each(obj, function(key, value) { key = key.charAt(0).toLowerCase() + key.slice(1); if (typeof value == "object" && !(value instanceof Array)) { value = convertKeysToCamelCase(value); } newObj[key] = value; }); return newObj; }; 

示例调用:

 var contact = { GivenName: "Matt", FamilyName:"Berry" }; console.log(convertKeysToCamelCase(contact)); // logs: Object { givenName="Matt", familyName="Berry"} console.log(convertKeysToCamelCase([contact])); // logs: [Object { givenName="Matt", familyName="Berry"}] console.log(convertKeysToCamelCase("string")); // logs: null console.log(contact); // logs: Object { GivenName="Matt", FamilyName="Berry"} 

这个解决方案基于上面的普通js解决方案,使用loadash并保留一个数组(如果作为参数传递)并且只更改密钥

 function camelCaseObject(o) { let newO, origKey, value if (o instanceof Array) { newO = [] for (origKey in o) { value = o[origKey] if (typeof value === 'object') { value = camelCaseObject(value) } newO.push(value) } } else { newO = {} for (origKey in o) { if (o.hasOwnProperty(origKey)) { newO[_.camelCase(origKey)] = o[origKey] } } } return newO } // Example const obj = [ {'my_key': 'value'}, {'Another_Key':'anotherValue'}, {'array_key': [{'me_too':2}] } ] console.log(camelCaseObject(obj)) 
  

使用来自https://plnkr.co/edit/jtsRo9yU12geH7fkQ0WL?p=preview的引用更新了代码这通过将数组保持为数组(可以使用map迭代)来处理包含其中对象的数组的对象等等

 function snakeToCamelCase(snake_case_object){ var camelCaseObject; if (isPlainObject(snake_case_object)) { camelCaseObject = {}; }else if(isArray(snake_case_object)){ camelCaseObject = []; } forEach( snake_case_object, function(value, key) { if (isPlainObject(value) || isArray(value)) { value = snakeToCamelCase(value); } if (isPlainObject(camelCaseObject)) { camelCaseObject[camelCase(key)] = value; }else if(isArray(camelCaseObject)){ camelCaseObject.push(value); } } ) return camelCaseObject; } 

接受了lodash和一些es6 +function的挑战以下是我使用reducefunction的实现。

 function deeplyToCamelCase(obj) { return _.reduce(obj, (camelCaseObj, value, key) => { const convertedDeepValue = _.isPlainObject(value) || _.isArray(value) ? deeplyToCamelCase(value) : value; return { ...camelCaseObj, [_.camelCase(key)] : convertedDeepValue }; }, {}); }; 

这是我的看法; 比brandoncode的实现更具可读性和更少的嵌套,并且有更多的空间来处理像Date这样的边缘情况(顺便说一下,处理不了)或null

 function convertPropertiesToCamelCase(instance) { if (instance instanceof Array) { var result = []; for (var i = 0; i < instance.length; i++) { result[i] = convertPropertiesToCamelCase(instance[i]); } return result; } if (typeof instance != 'object') { return instance; } var result = {}; for (var key in instance) { if (!instance.hasOwnProperty(key)) { continue; } result[key.charAt(0).toLowerCase() + key.substring(1)] = convertPropertiesToCamelCase(instance[key]); } return result; } 

使用lodash,你可以这样做:

 export const toCamelCase = obj => { return _.reduce(obj, (result, value, key) => { const finalValue = _.isPlainObject(value) || _.isArray(value) ? toCamelCase(value) : value; return { ...result, [_.camelCase(key)]: finalValue }; }, {}); };