【问题标题】:How to convert snake case to camelcase in my app如何在我的应用程序中将蛇壳转换为骆驼壳
【发布时间】:2016-11-20 23:22:35
【问题描述】:

我的 lodash 代码中有一个非常奇怪的问题

我有类似的东西

data = {
   'id':'123',
   'employee_name': 'John',
   'employee_type': 'new'  
}

var newObj = _.mapValues(data, function (value, key) {
     var t = _.camelCase(key);
     console.log(t) -> shows employeeName and employeeType

     return _.camelCase(key);
});

我期待我的 newObj 会变成

data = {
   'id':'123',
   'employeeName': 'John',
   'employeeType': 'new'  
}

在我运行上面的代码之后,它仍然保持原样

data = {
   'id':'123',
   'employee_name': 'John',
   'employee_type': 'new'  
}

这太奇怪了,我不确定出了什么问题。有人可以帮我解决这个问题吗?非常感谢!

【问题讨论】:

  • newObj 看起来像什么?另外,我认为 mapValues 会映射值,保持键不变
  • @JaromandaX { 'id':'id', 'employee_name':'employeeName', 'employ_type':'employType' } 我想我需要使用与 mapValues 不同的地图函数
  • 是的,因为您将值映射到键
  • @JaromandaX 但我在切换时收到 _.mapKeys is not a function 错误消息......很奇怪。
  • mapKeys 是您编写的函数还是您在 lodash 文档中找到的函数?

标签: javascript lodash


【解决方案1】:

使用_.mapKeys() 代替_.mapValues()

var data = {
   'id': '123',
   'employee_name': 'John',
   'employee_type': 'new'  
};

var newObj = _.mapKeys(data, (value, key) => _.camelCase(key));

console.log('newObj: ', newObj);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.2/lodash.min.js"></script>

如果您需要忽略多余的value 参数,您可以在_.camelCase() 上使用_.rearg() 来生成一个函数,该函数采用第二个参数(key)而不是第一个参数(value )。

var data = {
   'id': '123',
   'employee_name': 'John',
   'employee_type': 'new'  
};

var newObj = _.mapKeys(data, _.rearg(_.camelCase, 1));

console.log('newObj: ', newObj);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.2/lodash.min.js"></script>

【讨论】:

  • 你必须有 lodash 3.8.0 或更高版本 - mapValues 是在 2.4.0 版本中引入的......这样你就可以有一个没有另一个
【解决方案2】:

snake-case to camelCase 仅适用于字符串(ES6+):

const snakeToCamel = str =>
  str.toLowerCase().replace(/([-_][a-z])/g, group =>
    group
      .toUpperCase()
      .replace('-', '')
      .replace('_', '')
  );

结果:

console.log(snakeToCamel('TO_CAMEL')) //toCamel
console.log(snakeToCamel('to_camel')) //toCamel
console.log(snakeToCamel('TO-CAMEL')) //toCamel
console.log(snakeToCamel('to-camel')) //toCamel

【讨论】:

  • 可以简化为:str.toLowerCase().replace(/[-_][a-z]/g, (group) => group.slice(-1).toUpperCase());
  • 如果可以出现数字,比如我的情况,那么使用 str.toLowerCase().replace(/[-_][a-z0-9]/g, (group) => group。 slice(-1).toUpperCase());
  • 谢谢,这很好,但您也可以通过立即检查破折号或下划线字符并在发现时提前返回来使函数更加健壮。否则,调用者可能会使用“camelcase”之类的函数调用函数并得到“camelcase”的结果,因为总会有人滥用你的函数。所以像第一行的if ( !(/[_-]/).test(str) ) return str; 这样的东西可能会起作用。
【解决方案3】:

您也可以轻松地为此创建自己的函数:

function camelCase(obj) {
  var newObj = {};
  for (d in obj) {
    if (obj.hasOwnProperty(d)) {
      newObj[d.replace(/(\_\w)/g, function(k) {
        return k[1].toUpperCase();
      })] = obj[d];
    }
  }
  return newObj;
}

var data = {
  'id': '123',
  'employee_name': 'John',
  'employee_type': 'new'
}

console.log(camelCase(data));

【讨论】:

    【解决方案4】:

    是的,我不是图书馆的忠实粉丝。下面是如何在原生 Javascript 中做到这一点...

    let data = {
       'id':'123',
       'employee_name': 'John',
       'employee_type': 'new'  
    }
    
    // #1 simple function which converts a string from snake case to camel case ...
    const snakeToCamel = s => s.replace(/(_\w)/g, k => k[1].toUpperCase())
    
    // #2 create new data object with camelCase keys...
    data = Object.entries(data).reduce((x,[k,v]) => (x[snakeToCamel(k)]=v) && x, {})
    
    console.log(data)

    【讨论】:

      【解决方案5】:

      对于我的用例,我需要(或想要)一个可以处理任意 json 对象(包括嵌套对象、数组等)的函数。想出了这个,到目前为止似乎还在工作:

      const fromSnakeToCamel = (data) => {
        if (_.isArray(data)) {
          return _.map(data, fromSnakeToCamel);
        }
      
        if (_.isObject(data)) {
          return _(data)
            .mapKeys((v, k) => _.camelCase(k))
            .mapValues((v, k) => fromSnakeToCamel(v))
            .value();
        }
      
        return data;
      }
      

      请注意,如果它不是数组或对象,我只是返回数据,因为我实际上只想转换键。无论如何,希望这对某人有所帮助

      【讨论】:

        【解决方案6】:

        这些都是很好的答案,但它们不符合我的需要。我喜欢 Ashish 的回答,因为它处理嵌套对象,但是如果您想要的数据中有下划线怎么办?因此,这里是 Bambam 的答案的变体,可以使其递归,因为 lodash 有时会很痛苦。

        function toCamelCase (obj) {
            let rtn = obj
            if(!rtn) {
                return rtn
            } else if (typeof (obj) === 'object') {
                if (obj instanceof Array) {
                    rtn = obj.map(toCamelCase)
                } else {
                    rtn = {}
                    for (let key in obj) {
                        if (obj.hasOwnProperty(key)) {
                             const newKey = key.replace(/(_\w)/g, k => k[1].toUpperCase())
                             rtn[newKey] = toCamelCase(obj[key])
                        }
                    }
                }
            }
            return rtn
        }
        

        【讨论】:

        • 如果某个key的值为null,则会失败,因为typeof null === 'object'
        【解决方案7】:

        这是另一个使用简单 for 循环的答案。

        var data = {
           'id': '123',
           'employee_name': 'John',
           'employee_type': 'new'  
        };
        
        var output = {}
        for (var key in data) {
          output[_.camelCase(key)] = data[key];
        }
        

        【讨论】:

        • data[_.camelCase(key)] 应该是output [_.camelCase(key)]
        【解决方案8】:

        试试这个,它肯定会按预期工作。

        const helpers = {};
        
        helpers.camelize = function(str) {
            return str.trim().replace(/[A-Z]+/g, (letter, index) => {
                return index == 0 ? letter.toLowerCase() : '_' + letter.toLowerCase();
            }).replace(/(.(\_|-|\s)+.)/g, function(subStr) {
                return subStr[0]+(subStr[subStr.length-1].toUpperCase());
            });
        }
        
        
        helpers.camelizeKeys = function(data) {
            const result = {};
            for (const [key, val] of Object.entries(data)) {
                result[helpers.camelize(key)] = val;
            }
            return result;
        }
        
        helpers.camelizeNestedKeys = function(dataObj) {
            return JSON.parse(JSON.stringify(dataObj).trim().replace(/("\w+":)/g, function(keys) {
                return keys.replace(/[A-Z]+/g, (letter, index) => {
                    return index == 0 ? letter.toLowerCase() : '_' + letter.toLowerCase();
                }).replace(/(.(\_|-|\s)+.)/g, function(subStr) {
                    return subStr[0]+(subStr[subStr.length-1].toUpperCase());
                });
            }));
        }
        
        
        const data = {
            'id':'123',
            'employee_name': 'John',
            'employee_type': 'new'  
        };
        
        const nestedData = {
            'id':'123',
            'employee_name': 'John',
            'employee_type': 'new',
            'exployee_projects': [
                {"project_name": "test1", "project_year": 2004},
                {"project_name": "test2", "project_year": 2004}
            ]
        };
        
        
        // Few camelize Examples
        const str1 = "banana_orange_apple_mango";
        const str2 = "banana-orange-apple-mango";
        const str3 = "banana orange apple mango";
        const str4 = "BANANA Orange APPLE-mango";
        const str5 = "banana 5orange apple #mango";
        const str6 = "banana__orange-_apple5-#mango";
        
        console.log(helpers.camelize(str1));
        console.log(helpers.camelize(str2));
        console.log(helpers.camelize(str3));
        console.log(helpers.camelize(str4));
        console.log(helpers.camelize(str5));
        console.log(helpers.camelize(str6));
        
        console.log("=============================");
        
        // camelize object keys 
        console.log(helpers.camelizeKeys(data));
        
        console.log("=============================");
        
        // camelize nested object keys
        console.log(helpers.camelizeNestedKeys(nestedData));

        【讨论】:

          【解决方案9】:

          如果你想转换嵌套对象,那么使用 lodash 可能会有点痛苦。

          我尝试使用正则表达式、JSON.parse 和 JSON.stringify 这是相同的代码

          下面的代码返回具有驼峰格而不是蛇格的新对象

          //input
          var data = {
             'id': '123',
             'employee_name': 'John',
             'employee_type': {'new_name': 'foo'}  
          };
          
          JSON.parse(JSON.stringify(data).replace(
                          /(_\w)\w+":/g,
                          match => match[1].toUpperCase() + match.substring(2)
                        ));
          
          {
             'id': '123',
             'employeeName': 'John',
             'employeeType': {'newName': 'foo'}  
          }
          

          【讨论】:

          • 这不适用于具有多个下划线的键。例如“employee_full_name”
          【解决方案10】:

          根据 Abbos Tajimov 的回答(和 Ali 的评论),我们还可以利用 the arguments passed down to the inline function

          const snakeToCamel = str => {
            if (!(/[_-]/).test(str)) return str
          
            return str.toLowerCase()
              .replace(/([-_])([a-z])/g, (_match, _p1, p2) => p2.toUpperCase())
          }
          

          【讨论】:

            【解决方案11】:

            另一种方式

             _(data)
                 .keys()
                 .map(_.camelCase)
                 .zipObject(_.values(data))
                 .value()
            

            【讨论】:

              【解决方案12】:

              我真的很喜欢带有嵌套对象的 Mardok 版本,唯一的问题是它将“null”转换为 {}

              这是我的:

              import _ from 'lodash';
              
              export const toCamelCase: any = (obj: any) => {
                  let rtn = obj
                  if (typeof obj === 'object') {
                      if (obj instanceof Array) {
                          rtn = obj.map(toCamelCase)
                      }
                      else if (_.isEmpty(obj)) {
                          rtn = null
                      } else {
                          rtn = {}
                          for (let key in obj) {
                              if (obj.hasOwnProperty(key)) {
                                  const newKey = key.replace(/(_\w)/g, k => k[1].toUpperCase())
                                  rtn[newKey] = toCamelCase(obj[key])
                              }
                          }
                      }
                  }
                  return rtn
              }
              

              【讨论】:

              • 这里不需要 lodash。您可以简单地在第一个 if 中添加检查 && obj !==null
              【解决方案13】:

              递归创建骆驼对象。

              function camelCase(obj) {
                const newObj = {};
                for (const key in obj) {
                  if (obj.hasOwnProperty(key)) {
                      const value = obj[key];
                      const keyCamel = key.replace(/(\_\w)/g, (match) => match[1].toUpperCase());
                      const isRecursive = typeof value === 'object';
                      newObj[keyCamel] = isRecursive ? camelCase(value) : value;
                  }
                }
                return newObj;
              }
              
              let data = {
                id: '123',
                employee_name: 'John',
                inner: {
                  employee_type: 'new'
                },
              }
              
              camelCase(data);
              

              【讨论】:

                【解决方案14】:

                这个函数会递归地将对象中的所有snake case键转换为camelCase。包括数组中的对象和对象中的对象。

                const convertSnakeCaseToCamelCase = (obj) => {
                    let newObj = {};
                    if (typeof(obj) !== 'object') {
                        return obj;
                    } else if (Array.isArray(obj)) {
                        newObj = [];
                    }
                    for (const key in obj) {
                        const childObj = convertSnakeCaseToCamelCase(obj[key]);
                        if (Array.isArray(obj)) {
                            newObj.push(childObj);
                        } else {
                            const newKey = key.replace(/(\_\w)/g, (k) => k[1].toUpperCase());
                            newObj[newKey] = childObj;
                        }
                    }
                    return newObj;
                };
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2019-10-30
                  • 1970-01-01
                  • 2016-01-16
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多