Srishan Supertramp
Srishan Supertramp

Reputation: 395

Unflatten a dot-separated key/value pair into a nested object using Ramda

The Ramda cookbook explains here how to convert a nested object into dot-separated flattened object. I'm new to Ramda and I would like to learn how to do the reverse of the above.

It would convert this object:

{
  "company.name": "Name is required",
  "solarSystemInfo.name": "Name is required",
  "installer.business.name": "slkdfj is required"
}

to,

{
  "company": {
    "name": "Name is required"
  },
  "solarSystemInfo": {
    "name": "Name is required"
  },
  "installer": {
    "business": {
      "name": "slkdfj is requried"
    }
  }
}

A working fiddle using plain JS is here.

Upvotes: 0

Views: 1351

Answers (3)

Matteo Battista
Matteo Battista

Reputation: 1

From "Using Reduce you can avoid overwriting of objects with multiple keys."

If you are on Typescript project and you have "Cannot find key" or "val"... you can use:

const data = {
    "company.name": "Name is required",
    "solarSystemInfo.name": "Name is required",
    "installer.business.name": "Reg. name is required",
    "installer.business.code": "NYSE code is required"
}

const buildObj = (acc, value) => {
  const [key,val] = value
  return R.assocPath(R.split('.', key), val, acc);
}

const unflattenObj = R.pipe(
  R.toPairs,
  R.reduce(buildObj,{})
)

console.log(unflattenObj(data))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>

Upvotes: 0

Inda Vidjool
Inda Vidjool

Reputation: 301

Using Reduce you can avoid overwriting of objects with multiple keys.

const data = {
    "company.name": "Name is required",
    "solarSystemInfo.name": "Name is required",
    "installer.business.name": "Reg. name is required",
    "installer.business.code": "NYSE code is required"
}
const buildObj = (acc,value) => {
    [key,val]=value;
    return R.assocPath(R.split('.', key), val, acc);
}

const unflattenObj = R.pipe(
    R.toPairs,
    R.reduce(buildObj,{})
);
console.log(unflattenObj(data));
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>

Upvotes: 2

Scott Christopher
Scott Christopher

Reputation: 6516

This can be achieved by splitting the object into pairs using R.toPairs, then "unflattening" each pair into an object by splitting the key on each . into a list and passing that as the path to R.assocPath to build out the object. This will result in a list of objects that can then be merged together using R.mergeAll.

const data = {
  "company.name": "Name is required",
  "solarSystemInfo.name": "Name is required",
  "installer.business.name": "slkdfj is required"
}

const pathPairToObj = (key, val) =>
  R.assocPath(R.split('.', key), val, {})

const unflattenObj = R.pipe(
  R.toPairs,
  R.map(R.apply(pathPairToObj)),
  R.mergeAll
)

console.log(unflattenObj(data))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>

Upvotes: 3

Related Questions