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

Jon*_*lls 54 javascript jquery json underscore.js

我从这样的API返回JSON:

Contacts: [{ GivenName: "Matt", FamilyName:"Berry" }]
Run Code Online (Sandbox Code Playgroud)

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

 contacts: [{ givenName: "Matt", familyName:"Berry" }]
Run Code Online (Sandbox Code Playgroud)

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

var jsonContacts = json["Contacts"],
    contacts= [];

_.each(jsonContacts , function(item){
    var contact = new Contact( item.GivenName, item.FamilyName );
    contacts.push(contact);
});
Run Code Online (Sandbox Code Playgroud)

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

bra*_*ipt 68

这是一个可靠的递归函数,可以正确地使用所有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
}
Run Code Online (Sandbox Code Playgroud)

测试:

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

console.log(JSON.stringify(toCamel(obj)))
Run Code Online (Sandbox Code Playgroud)

输出:

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

  • @brandonscript它实际上会错过是否有任何属性是数组,您的属性仅检查主对象是否是数组。此行缺少检查是否为数组:`if (value !== null && value.constructor === Object)` 这是您失败的示例:https://plnkr.co/edit/tEBYU3pQmJJZyl84CFo5检查数组的修复:https://plnkr.co/edit/78gDwcLChAOT31XGoLG6 (3认同)
  • 如果 o 是 Date 对象(或任何没有自己属性的对象),这将丢失值信息。查看演示 http://codepen.io/anon/pen/EPqZLY?editors=1010 (2认同)

mik*_*1aj 61

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

_.mapKeys(obj, (v, k) => _.camelCase(k))
Run Code Online (Sandbox Code Playgroud)

这都转换TitleCasesnake_casecamelCase.请注意,它不是递归的.

  • 注意:这不适用于嵌套属性,仅适用于顶级键。 (9认同)

gor*_*rds 19

要将普通对象的键更改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;
};
Run Code Online (Sandbox Code Playgroud)

在这个PLUNKER中测试

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

  • 请注意,如果传递给它,这将使数组变平 - 并返回一个对象 (4认同)
  • 正如@GalBracha所说,这似乎并不将数组保持为数组。我改为一起砍掉这个:https://plnkr.co/edit/OnLVNqq7dHW1T3ukuyd1 (2认同)

jes*_*hio 12

谢谢其他我这样做(使用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;
};
Run Code Online (Sandbox Code Playgroud)

测试:

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

console.log(JSON.stringify(camelizeKeys(obj)))
Run Code Online (Sandbox Code Playgroud)

输出:

{  
   "firstName": "John",
   "lastName": "Smith",
   "birthDate": "2018-05-31T09:03:57.844Z",
   "arrayTest":[  
      "one",
      "TWO",
      3
   ],
   "thisKey":{  
      "thisSubKey": 42
   }
}
Run Code Online (Sandbox Code Playgroud)

  • 这应该是公认的答案 - 最新的 (4认同)
  • 多谢。工作正常。我会将 `obj !== null && obj.constructor === Object` 替换为 `_.isPlainObject(obj)` (2认同)

小智 10

只需使用驼峰

humps.camelize('hello_world');
humps.camelizeKeys(object, options); // will work through entire object
Run Code Online (Sandbox Code Playgroud)

https://www.npmjs.com/package/humps


gua*_*de2 6

使用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) }), {}));
Run Code Online (Sandbox Code Playgroud)

展开:

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) 
    };
  }, {});
};      
Run Code Online (Sandbox Code Playgroud)

  • 如果我们有这样的对象,这将失败: [{ hello: 0 }, { hello: null }, { hello: undefined }, { hello: false }] 它将返回 [{hello: {}}, {hello: { }}, {hello: {}), {hello: {}}] 可以通过添加 if (obj === 0 || obj === null || obj === undefined || obj === false 来修复) { 返回对象; } (3认同)

dai*_*no3 6

这是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)
    }
}
Run Code Online (Sandbox Code Playgroud)

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


shu*_*111 5

有一个很好的 npm 模块。 https://www.npmjs.com/package/camelcase-keys

npm install camelcase-keys
Run Code Online (Sandbox Code Playgroud)
const camelcaseKeys = require( "camelcase-keys" );

camelcaseKeys( { Contacts: [ { GivenName: "Matt", FamilyName: "Berry" } ] }, { deep: true } );
Run Code Online (Sandbox Code Playgroud)

将返回...

{ contacts: [ { givenName: "Matt", familyName: "Berry" } ] }
Run Code Online (Sandbox Code Playgroud)

  • 我特别喜欢这个答案,因为整个包大约 9kb。在反应框架内对我来说效果很好,感谢您的回答! (2认同)