This works by converting our object into a format like this:
[
[["ban_Name"], "test"],
[["bank"], "yes"],
[["conts", 0, "counterName"], "Cname1"],
[["conts", 0, "obl"], "obl1"],
[["conts", 0, "orig"], "orig 1"],
[["conts", 1, "counterName"], "Cname2"],
[["conts", 1, "obl"], "obl2"],
[["conts", 1, "orig"], "orig 2"],
[["cont"], "yes"],
[["creditors"], "no"]
]
and then using a generic hydrate
function that takes an array of path-value pairs like this and puts them together into an object:
// utility functions
const setPath = ([p, ...ps]) => (v) => (o) =>
p == undefined ? v : Object .assign (
Array .isArray (o) || Number.isInteger (p) ? [] : {},
{...o, [p]: setPath (ps) (v) ((o || {}) [p])}
)
const hydrate = (xs) =>
xs .reduce ((a, [p, v]) => setPath (p) (v) (a), {})
// helper function
const makePath = (k, parts = k .match (/^cont_(\d+)\-(.+)$/)) =>
parts ? ['conts', parts [1] - 1, parts [2]] : [k]
// main function
const convert = (input) =>
hydrate (Object .entries (input) .map (([k, v]) => [makePath (k), v]))
// sample data
const values = {'ban_Name': "test", 'bank': "yes", 'cont_1-counterName': "Cname1", 'cont_1-obl': "obl1", 'cont_1-orig': "orig 1", 'cont_2-counterName': "Cname2", 'cont_2-obl': "obl2", 'cont_2-orig': "orig 2", 'cont': "yes", 'creditors': "no"}
// demo
console .log (convert (values))
.as-console-wrapper {max-height: 100% !important; top: 0}
setPath
is a generic utility function that takes a path like ['a', 'b', 'c']
, a value like 42, and an object like {a: {b: {d: 1}}, e: 2}
and adds the value along that path to (a copy of) that object, yielding something like {a: {b: {c: 42, d: 1}}, e: 2}
.
hydrate
is similar to Object .fromEntries
except that it uses a path rather than a key, so can build nested objects from a flat list.
We have the helper function makePath
which takes a plain key like 'bank'
and returns ['bank']
or takes one of your formatted keys like 'cont_2-orig'
and returns ['conts', 2, 'orig']
.
Then our main function simply needs to map over the entries in the input object, converting the keys with makePath
, then hydrate an object with the resulting array.
Note that hydrate
and setPath
are genuinely reusable functions that you might want in multiple parts of your application, and so probably belong in some sort of utility library. The only custom code here is makePath
and convert
, and those are quite simple.