Skip to content

Instantly share code, notes, and snippets.

@scott1028
Last active March 5, 2023 12:13
Show Gist options
  • Save scott1028/e5ae9c19fad75ed76087b122412532ba to your computer and use it in GitHub Desktop.
Save scott1028/e5ae9c19fad75ed76087b122412532ba to your computer and use it in GitHub Desktop.
Dynamical mapper generator by pre-defined template path
const _ = require('lodash');
const template = {
questionnaireIdToQuestionSeq: {
'$sections.0.questionData.id$': '01',
v: {
'$aaaa.bb.cc$': {
'$nn.qq.aa$': [
'$sections.0.questionData.id$',
'$sections.0.questionData.id$',
'$sections.1.questionData.id$',
],
}
},
},
question01: {
questionIds: [
'$sections.0.questionData.id$',
'$sections.1.questionData.id$',
],
answerIds: null
},
}
const traverseMapper = ({
path = [],
target = undefined,
template = target,
output = _.isArray(target) ? [] : {},
formatter = value => value,
} = {}) => {
const handler = ({ template, path, value }) => {
for(let idx = 0; idx < path.length; idx++) {
const basePath = path.slice(0, idx + 1);
const templateType = _.chain(template).get(basePath).isArray().value() ? [] : _.chain(template).get(basePath).isObject().value() ? {} : 'leaf';
const formattedPath = formatter(basePath);
if (templateType !== 'leaf') {
let initValue = _.chain(template).get(basePath).value() || templateType;
if (_.isArray(initValue)) {
if (_.chain(output).get(formattedPath).isEmpty().value()) {
_.chain(output).set(formattedPath, templateType).value();
}
} else {
if (_.chain(output).get(formattedPath).isEmpty().value()) {
_.chain(output).set(formattedPath, templateType).value();
}
}
} else {
// array -> push, object -> set directly
if (_.chain(formattedPath).last().isNumber().value()) {
_.chain(output).get(formattedPath.slice(0, -1)).push(formatter(value)).value();
} else {
_.chain(output).set(formattedPath, formatter(value)).value();
}
}
}
};
if (_.isArray(target)) {
if (_.isEmpty(target)) {
// empty array: []
handler({ template, path, value: target });
} else {
target.forEach((item, idx) => {
traverseMapper({ template, path: [...path, idx], target: item, output, formatter });
});
}
} else if (_.isObject(target)) {
if (_.isEmpty(target)) {
// empty object: {}
handler({ template, path, value: target, output });
} else {
for (let key in target) {
traverseMapper({ template, path: [...path, key], target: target[key], output, formatter });
}
}
} else {
// pure value: string, number, undefined, null
handler({ template, path, value: target });
}
return output;
}
const data = {
sections: [{questionData: {id: 'scott-id'}}, {questionData: {id: 'scott-id.1'}}],
aaaa: { bb: { cc: 'scott-cc' } },
nn: { qq: { aa: 'scott-aa' } },
};
const data2 = {
sections: [{questionData: {id: 'alan-id'}}, {questionData: {id: 'alan-id.1'}}],
aaaa: { bb: { cc: 'alan-cc' } },
nn: { qq: { aa: 'alan-aa' } },
};
const getFormatter = data => (path) => {
const handler = item => {
const output = _.isString(item) ? item.replace(/\$/g, '') : item;
if (output !== item) {
return _.chain(data).get(output).value();
}
return output;
}
if (_.isArray(path)) {
return path.map(item => handler(item));
}
return handler(path);
};
const output = _.isArray(template) ? [] : {}
traverseMapper({ target: template, formatter: getFormatter(data), output });
traverseMapper({ target: template, formatter: getFormatter(data2), output });
// unittest
console.log('template:', JSON.stringify(template, null, 2));
console.log();
console.log('output:', JSON.stringify(output, null, 2));
/*
template: {
"questionnaireIdToQuestionSeq": {
"$sections.0.questionData.id$": "01",
"v": {
"$aaaa.bb.cc$": {
"$nn.qq.aa$": [
"$sections.0.questionData.id$",
"$sections.0.questionData.id$",
"$sections.1.questionData.id$"
]
}
}
},
"question01": {
"questionIds": [
"$sections.0.questionData.id$",
"$sections.1.questionData.id$"
],
"answerIds": null
}
}
output: {
"questionnaireIdToQuestionSeq": {
"scott-id": "01",
"v": {
"scott-cc": {
"scott-aa": [
"scott-id",
"scott-id",
"scott-id.1"
]
},
"alan-cc": {
"alan-aa": [
"alan-id",
"alan-id",
"alan-id.1"
]
}
},
"alan-id": "01"
},
"question01": {
"questionIds": [
"scott-id",
"scott-id.1",
"alan-id",
"alan-id.1"
],
"answerIds": null
}
}
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment