Skip to content

Commit 5d6db78

Browse files
authored
Merge pull request #39 from jsertx/feat/add-transform-keys-to-snake
feat: add transformKeysToSnake
2 parents 1713930 + f1781af commit 5d6db78

File tree

7 files changed

+141
-1
lines changed

7 files changed

+141
-1
lines changed

CHANGELOG

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
#1.20.0
2+
- feat: add transformKeysToSnake
3+
14
#1.19.1
25
- fix: fix isPlainObject to check that the constructor is an object
36

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ Currently supported utils:
4444
- `snakeCase` - convert camel case and string/dash separated strings to snake case
4545
- `sum` - calculate sum of array items
4646
- `sumBy` - calculate sum of array items using iteratee function or string shortcut
47+
- `transformKeysToSnake` - transform every object key to snake case with option to be recursive
4748
- `union` - Returns the union of the given arrays
4849
- `uniqBy` - get unique values of array by the iteratee function or property path
4950
- `uniqWith` - Returns a new array with unique values, using a comparator function

index.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export function shuffle<T> (array: Array<T>): Array<T>
4040
export function snakeCase (str: string): string
4141
export function sum (values: Array<string>): number
4242
export function sumBy (values: Array, iteratee: Function | string): number
43+
export function transformKeysToSnake (obj: Object, opts?: {recursive?: boolean}) : Object
4344
export function union (...arrays: Array[]): Array
4445
export function uniqBy (array: Array, iteratee: Function | string): Array
4546
export function uniqWith (array: Array, comparator: Function): Array

index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ const shuffle = require('./src/shuffle')
4242
const snakeCase = require('./src/snakeCase')
4343
const sum = require('./src/sum')
4444
const sumBy = require('./src/sumBy')
45+
const transformKeysToSnake = require('./src/transformKeysToSnake')
4546
const union = require('./src/union')
4647
const uniqBy = require('./src/uniqBy')
4748
const uniqWith = require('./src/uniqWith')
@@ -93,6 +94,7 @@ module.exports = {
9394
snakeCase,
9495
sum,
9596
sumBy,
97+
transformKeysToSnake,
9698
union,
9799
uniqBy,
98100
uniqWith,

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@bitfinexcom/lib-js-util-base",
3-
"version": "1.19.1",
3+
"version": "1.20.0",
44
"description": "general utils",
55
"main": "index.js",
66
"scripts": {

src/transformKeysToSnake.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
'use strict'
2+
3+
const isPlainObject = require('./isPlainObject')
4+
const snakeCase = require('./snakeCase')
5+
6+
/**
7+
* Transform object keys to snake case
8+
* e.g. { fooBar: 1 } => { foo_bar: 1 }
9+
* @param {Object} obj
10+
* @param {Object} [opts]
11+
* @param {boolean} [opts.recursive]
12+
* @returns {Object}
13+
*/
14+
const transformKeysToSnake = (obj, opts) => {
15+
if (Array.isArray(obj)) {
16+
return obj.map(item => transformKeysToSnake(item, opts))
17+
}
18+
19+
if (!isPlainObject(obj)) {
20+
return obj
21+
}
22+
23+
return Object.fromEntries(
24+
Object.entries(obj).map(([k, v]) => [
25+
snakeCase(k),
26+
opts?.recursive ? transformKeysToSnake(v, opts) : v
27+
])
28+
)
29+
}
30+
31+
module.exports = transformKeysToSnake

test/transformKeystoSnake.js

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
'use strict'
2+
3+
/* eslint-env mocha */
4+
5+
const assert = require('assert')
6+
const { transformKeysToSnake } = require('../index')
7+
const { itEach } = require('mocha-it-each')
8+
9+
describe('transformKeysToSnake', () => {
10+
describe('non recursive (default)', () => {
11+
itEach('should return input when it is not an object', [new Date(), null, false], (input) => {
12+
assert.equal(transformKeysToSnake(input), input)
13+
})
14+
15+
it('should return input with snake case props recursively', () => {
16+
const input = {
17+
camelProp: 'true',
18+
nestedProp: {
19+
first_name: 'john',
20+
lastName: 'doe',
21+
tags: ['keepCamel']
22+
},
23+
someObjs: [
24+
{ someProp: 'value' },
25+
{ foo_bar: 'value', foo: 'value' }
26+
]
27+
}
28+
const output = {
29+
camel_prop: 'true',
30+
nested_prop: {
31+
first_name: 'john',
32+
lastName: 'doe',
33+
tags: ['keepCamel']
34+
},
35+
some_objs: [
36+
{ someProp: 'value' },
37+
{ foo_bar: 'value', foo: 'value' }
38+
]
39+
}
40+
assert.deepEqual(transformKeysToSnake(input), output)
41+
})
42+
43+
it('should work with array mix of object and nested arrays', () => {
44+
const input = {
45+
mixedArray: [123, { someKey: 'value' }, [{ nestedArrayItem: 'test' }]]
46+
}
47+
const output = {
48+
mixed_array: [123, { someKey: 'value' }, [{ nestedArrayItem: 'test' }]]
49+
}
50+
assert.deepEqual(transformKeysToSnake(input), output)
51+
})
52+
})
53+
describe('recursive', () => {
54+
itEach('should return input when it is not an object', [new Date(), null, false], (input) => {
55+
assert.equal(transformKeysToSnake(input, { recursive: true }), input)
56+
})
57+
58+
it('should return input with snake case props recursively', () => {
59+
const input = {
60+
camelProp: 'true',
61+
nestedProp: {
62+
first_name: 'john',
63+
lastName: 'doe',
64+
level2: {
65+
fooBar: 'x'
66+
},
67+
tags: ['keepCamel']
68+
},
69+
someObjs: [
70+
{ someProp: 'value' },
71+
{ foo_bar: 'value', foo: 'value' }
72+
]
73+
}
74+
const output = {
75+
camel_prop: 'true',
76+
nested_prop: {
77+
first_name: 'john',
78+
last_name: 'doe',
79+
level2: {
80+
foo_bar: 'x'
81+
},
82+
tags: ['keepCamel']
83+
},
84+
some_objs: [
85+
{ some_prop: 'value' },
86+
{ foo_bar: 'value', foo: 'value' }
87+
]
88+
}
89+
assert.deepEqual(transformKeysToSnake(input, { recursive: true }), output)
90+
})
91+
92+
it('should work with array mix of object and nested arrays', () => {
93+
const input = {
94+
mixedArray: [123, { someKey: 'value' }, [{ nestedArrayItem: 'test' }]]
95+
}
96+
const output = {
97+
mixed_array: [123, { some_key: 'value' }, [{ nested_array_item: 'test' }]]
98+
}
99+
assert.deepEqual(transformKeysToSnake(input, { recursive: true }), output)
100+
})
101+
})
102+
})

0 commit comments

Comments
 (0)