0
\$\begingroup\$

Something I've found myself having to do reasonably often is map properties from an Object (usually a heavily nested MongoDB document) to a different 'shape' to then pass it to a function call or API endpoint etc. Combine this with a development environment in which these 'shapes' are prone to change and it felt messy to do the mapping manually each time (though learning object destructuring often made it much neater!).

I've written this code to accept two arrays containing key names, an object and a delimiter option. The function then returns an object containing the properties pointed to by the keys in the input array, but with the key names as specified in the output array.

const transposeObjectByArraysOfPairs = (input, output, object, delimiter = '.') => {
    const toReturn = {};

    input.map((keyString, idx) => {
        const keysIn = keyString.split(delimiter);

        // copy object to avoid mutating original
        let _currentProp = Object.assign({}, object);

        for (let i = 0; i < keysIn.length; i++) {
            _currentProp = _currentProp[keysIn[i]];
        }

        const keysOut = output[idx].split(delimiter);

        let len = keysOut.length;

        let _obj = {[keysOut[len - 1]]: _currentProp};

        for (let j = len - 2 ; j >= 0; --j) {
            _obj = {[keysOut[j]]: _obj};
        }

        Object.assign(toReturn, _obj);
    });

    return toReturn;
};

const object = {a : {b: { c: 10, d: 30 }}};

const input = ['a.b.c', 'a.b.d'];
const output = ['A.B', 'B.C'];

console.log(misc.transposeObjectByArraysOfPairs(input, output, object));
// { A: { B: 10 }, B: { C: 30 } }

Whilst this function has neatened up chunks of my code significantly, I can't help but feel there's a neater way to do this. Iterating through an array of keys to get to the desired property feels quite hacky in particular.

In a perfect world I think I'd essentially have a function that mapped from one object schema to another and then I could simply maintain schema and know that if I made changes, I wouldn't need to modify the code that did the mapping.

\$\endgroup\$
1
\$\begingroup\$

Maybe I don't understand the question exactly, but what's stopping you from just creating a function to do the mapping, like this:

function obj1ToObj2(obj1){
    return {
        A: {
            B: obj1.a.b.c
        },
        B: {
            C: obj1.a.b.d
        }
    }
}
\$\endgroup\$
  • \$\begingroup\$ Nothing really! In my experience though it can become quite unwieldy when you've got a large number of properties to map. I guess one could quite happily argue it's no less unwieldy than an arrays of key name pairs though! My hope is that there's a neat solution whereby one maintains a template or schema for each object and then mapping is taken care off based upon those. \$\endgroup\$ – Batters Oct 19 '18 at 19:30
  • 1
    \$\begingroup\$ Oh I see. Not sure if that's possible though, since there's basically an infinite number of possible mappings. \$\endgroup\$ – Magnus Jeffs Tovslid Oct 19 '18 at 20:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.