如何将 snake_case 转换为 camelCase?

问题描述 投票:0回答:20

我有类似的东西

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'  
}
javascript lodash
20个回答
42
投票

将 snake_case 或 kebab-case 替换为 camelCase only for string (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

29
投票

使用

_.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
参数,您可以在_.rearg()
上使用
_.camelCase()
生成一个函数,该函数采用第二个参数(
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>


12
投票

您还可以轻松地为此创建自己的功能:

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


8
投票

这里是如何在原生 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;
}

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


5
投票

打字稿

一如既往,没有人要求打字稿版本,但在这里,请不要打我^-^。

没有
_
,没有
RegExp

  • 我将功能分成两个模块,但您可以通过适当的命名将它们放在外面

  • 我用

    never
    来标记类型实际上是正确的,因为 TS 并不总是知道它是否正确。

  • 你仍然可以使用

    _
    并缩短代码,但我想分解这个过程。


module CaseTransform {
  export type Snake = Lowercase<`${string}_${string}`>
  export type Camel = Capitalize<string> | `${Capitalize<string>}${Capitalize<string>}`

  export type SnakeToCamel<S extends string> = S extends `${infer Start}_${infer Rest}` ? `${Start}${Capitalize<SnakeToCamel<Rest>>}` : S
  type SnakeToCamel__TEST__ = SnakeToCamel<"my_account_profile"> // myAccountProfile

  export function capitalize<S extends string>(string: S): Capitalize<S> {
    if (string.length === 0) return "" as never

    return (string[0].toUpperCase() + string.slice(1)) as never
  }
  export function snakeToCamel<S extends string>(string: S): SnakeToCamel<S> {
    const [start, ...rest] = string.split("_")

    return (start + rest.map(capitalize).join("")) as never
  }
  const snakeToCamel__TEST__ = snakeToCamel("ASD_asd_asdad_")
}

module ObjectTransform {
  export function snakeToCamel<O extends object, K extends keyof O>(object: O): { [P in K as (P extends CaseTransform.Snake ? CaseTransform.SnakeToCamel<P> : P)]: O[P] } {
    return Object
      .entries(object)
      .reduce((result, [key, value]) => ({
        ...result,
        [CaseTransform.snakeToCamel(key)]: value
      }), {}) as never
  }
}

const sample = {
  id: 123,
  employee_name: "John",
  employee_type: "new",

  camelCase: "123",
  PascalCase: "123"
}
const __TEST__ = ObjectTransform.snakeToCamel(sample)

注意

如果您希望所有字符(甚至缩写)都为小写,请在

.toLowercase()
之后放置
string
并将
SnakeToCamel
类型更改为

type SnakeToCamel<S extends string> = S extends `${infer Start}_${infer Rest}` ? `${Lowercase<Start>}${Capitalize<SnakeToCamel<Rest>>}` : Lowercase<S>

简单!

打字结果

JavaScript 游乐场

function capitalize(string) {
  if (string.length === 0) return ""

  return (string[0].toUpperCase() + string.slice(1))
}
function snakeToCamel(string){
  const [start, ...rest] = string.split("_")

  return (start + rest.map(capitalize).join(""))
}
const snakeToCamel__TEST__ = snakeToCamel("ASD_asd_asdad_")
console.log(snakeToCamel__TEST__)

function objectKeysSnakeToCamel(object) {
  return Object
    .entries(object)
    .reduce((result, [key, value]) => ({
      ...result,
      [snakeToCamel(key)]: value
    }), {})
}

const sample = {
  id: 123,
  employee_name: "John",
  employee_type: "new",

  camelCase: "123",
  PascalCase: "123"
}
const __TEST__ = objectKeysSnakeToCamel(sample)
console.log(__TEST__)


3
投票

这些都是很好的答案,但它们不符合我的需要。我喜欢 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
}

3
投票
  camelCase(str) {
    return str
      .toLowerCase()
      .replace(/([-_][a-z])/g, (ltr) => ltr.toUpperCase())
      .replace(/[^a-zA-Z]/g, '')
  }

2
投票

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

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

var output = {}
for (var key in data) {
  output[_.camelCase(key)] = data[key];
}

2
投票

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

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


1
投票

如果你想转换嵌套对象,那么使用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'}  
}

1
投票

根据 Abbos Tajimov 的回答(和 Ali 的评论),我们还可以利用传递给内联函数的参数

const snakeToCamel = str => {
  if (!(/[_-]/).test(str)) return str

  return str.toLowerCase()
    .replace(/([-_])([a-z])/g, (_match, _p1, p2) => p2.toUpperCase())
}

0
投票

另一种方式

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

0
投票

我真的很喜欢带有嵌套对象的 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
}

0
投票

递归创建骆驼化对象。

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

0
投票

在 typeorm repo 中找到https://github.com/typeorm/typeorm/blob/master/src/util/StringUtils.ts#L8

export function camelCase(str: string, firstCapital: boolean = false): string {
    return str.replace(
        /^([A-Z])|[\s-_](\w)/g,
        function (match, p1, p2, offset) {
            if (firstCapital === true && offset === 0) return p1
            if (p2) return p2.toUpperCase()
            return p1.toLowerCase()
        },
    )
}

0
投票

只需将值传递给输入,结果将是驼峰式:

const snakeToCamel = input =>
  console.log(
    input.slice(0, input.indexOf('_')).toLowerCase() +
    input[input.indexOf('_') + 1].toUpperCase() +
    input.slice(input.indexOf('_') + 2)
  );
const inputs = [
  'underscore_case',
  'first_name',
  'Some_Variable',
  'calculate_AGE',
  'delayed_departure',
  'Hello_you',
  'hAI_i',
];
for (let input of inputs) {
  snakeToCamel(input);
}


0
投票

如果您的数据中有数组,您可以使用此代码:

const data = {
    vt_core_random: {
        user_details: {
        first_name: "xyz",
        last_name: "abc",
        groups: [
            {
            id: 1,
            group_type: "EXT"
            },
            {
            id: 2,
            group_type: "INT"
            }
        ],
        address_type: {
            city_name: "nashik",
            state: {
            code_name: "MH",
            name: "Maharashtra"
            }
        }
        }
    }
    };
let newObject = {};
const rename = key => {
    if(key.includes("_")){
        return key.replace(/_([a-z])/g, function (g) { return g[1].toUpperCase(); });
    }else return key
}
const convert = (data) => {
        if(typeof data === 'object'){

            if(Object.keys(data).length === 0){
                return true;
            }else{
                for (const key in data)
                {
                    const newKey = rename(key);
                    data[newKey] = data[key];
                    newKey !== key && delete data[key]
                    if(Array.isArray(data[newKey])) data[newKey].map(item => convert(item) )
                    else convert(data[newKey]) 
                }
            }
        }
    
}
convert(data);

console.log("Result: ", data)


0
投票

没有正则表达式或其他库的另一个选项:

const convertObjectFromSnakeCaseToCamelCase = (obj) => {
    Object.entries(obj).forEach(([k, v]) => {
        delete obj[k];
        obj[camelCaseXMLFieldName(k)] = v;      
    });
    return obj;
}

const camelCaseXMLFieldName = (key) => {
    return key.toLowerCase().split("_").map(((part, i) => (i > 0) ? part.charAt(0).toUpperCase() + part.slice(1) : part)).join("");
}

console.log(convertObjectFromSnakeCaseToCamelCase({
    'id': '123',
    'TEsT': 'Doe',
    'employee_name': 'John',
    'employee_type': 'new'
}));


-1
投票

这个函数会递归地将对象中的所有snake case keys转换为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;
};
© www.soinside.com 2019 - 2024. All rights reserved.