Skip to content

Instantly share code, notes, and snippets.

@tennox
Created June 4, 2020 09:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tennox/dfd44bcc4f8897b07dca93b6bc66dcdf to your computer and use it in GitHub Desktop.
Save tennox/dfd44bcc4f8897b07dca93b6bc66dcdf to your computer and use it in GitHub Desktop.
JS Object field mapper
import _ from 'lodash'
/**
* Map fields of an object:
*
* ```
* ObjectUtils.mapFields(
* { a: 1, b: 2, c: 3, d: 4 },
* {
* a: num => num + 10,
* b: { newB: num => num + 20 },
* c: { C1: num => num + 20, C2: num => num + 30 }
* }
* )
* ```
* -> `{ d: 4, a: 11, newB: 22, C1: 23, C2: 33 }`
*
* @param {Object} obj Source object
* @param {Object} mapper Map definition
*/
mapFields(obj, mapper) {
const newObj = _.omit(obj, _.keys(mapper));
for (const [oldKey, mapDef] of _.toPairs(mapper)) {
const oldValue = obj[oldKey]
let newFields;
if (typeof mapDef === 'function') {
newFields = { [oldKey]: mapDef(oldValue) }
} else if (_.isPlainObject(mapDef)) {
newFields = _.mapValues(mapDef, (mapDefSingleField, newKey) => {
if (typeof mapDefSingleField === 'function') {
return mapDefSingleField(oldValue)
}
throw new Error(`invalid map definition type: ${typeof mapDefSingleField} for ${oldKey}->${newKey}`)
})
} else
throw new Error(`invalid map definition type: ${typeof mapDef} for ${oldKey}`)
_.assignWith(newObj, newFields, (oldVal, newVal, field) => {
if (oldVal === undefined) return newVal;
if (_.has(obj, field) && !_.has(mapper, field))
throw new Error(`Re-mapping existing field '${field}'`)
else
throw new Error(`Duplicate mapping for '${field}': ${oldVal}, ${newVal}`)
})
}
return newObj
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment