Created
June 4, 2020 09:51
-
-
Save tennox/dfd44bcc4f8897b07dca93b6bc66dcdf to your computer and use it in GitHub Desktop.
JS Object field mapper
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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