1

I retrieve the following array of string values

[
"Module1.resource1.create",
"Module1.resource1.read",
"Module1.resource1.update",
"Module1.resource1.delete",
...
"Module1.resourceN.create",
"Module1.resourceN.read",
"Module1.resourceN.update",
]

I would like to change them to json format like this

{"privileges": {
 "Module1": {
 "resource1": {
 "create": true,
 "read": true,
 "update": true,
 "delete": true,
 },
...
 "resourceN": {
 "create": true,
 "read": true,
 "update": true,
 }
 }
 }
}

All I can think of is run a loop for each string, use split(".") and then somehow change it to json object. the problem I'm having is that the json is not a simple key: value, it's more of a key: object: object: object: value if that makes sense ...

I would appreciate the nudge in the right direction.

cheers

asked Aug 30, 2018 at 15:09
4
  • 2
    IMO the loop and split is the way to go Commented Aug 30, 2018 at 15:11
  • @jonatjano but not sure how to change the array to multi dimentional json... I can do key: value. but not sure how to do key: object: object: key: value if you know what I mean ... Commented Aug 30, 2018 at 15:13
  • are they always going to be in order? Commented Aug 30, 2018 at 15:19
  • @zfrisch - that cannot be guaranteed. Commented Aug 30, 2018 at 15:33

5 Answers 5

2

You can use Array#reduce method:

const result = { privileges: {} };
items.reduce((ret, el) => {
 // Split the array elements and use destructuring assignment syntax for
 // creating constants
 const [module, resource, verb] = el.split('.');
 // check if privileges[module] property exists. If not, define it as an empty object.
 if (!ret[module]) ret[module] = {};
 // follows the previous line's logic for resources!
 if (!ret[module][resource]) ret[module][resource] = {};
 ret[module][resource][verb] = true;
 return ret;
}, result.privileges);

Demo | Destructuring assignment syntax

answered Aug 30, 2018 at 15:23
Sign up to request clarification or add additional context in comments.

4 Comments

that works exactly as I want it to work! thanks. However, I don't really understand what is happening there.. Is it too much to ask for some explanation? I would appreciate that.
You are welcome! I'll add some comments to the code.
thank you. It's always better to understand than just copy and paste :)
interesting. I never knew about Destructuring assignment syntax, this will come in handy :) thanks
1

May be using dot-object will help without reinventing the wheel:

https://github.com/rhalff/dot-object

answered Aug 30, 2018 at 15:23

1 Comment

Good find! Even though I think the question is more about how to achieve that from the coding side.
1

This took a while, but does the job:

const rules = [
 "Module1.resource1.create",
 "Module1.resource1.read",
 "Module1.resource1.update",
 "Module1.resource1.delete",
 "Module1.resourceN.create",
 "Module1.resourceN.read",
 "Module1.resourceN.update",
 ].map(rule => rule.split('.'));
 
const res = { privileges: {} };
for (const rule of rules) {
 for (i = 0; i < rule.length; i++) {
 switch (i) {
 case 0: 
 res.privileges[rule[0]] = Object.assign({}, res.privileges[rule[0]])
 break;
 case 1:
 res.privileges[rule[0]][rule[1]] = Object.assign({}, res.privileges[rule[0]][rule[1]])
 break;
 case 2:
 res.privileges[rule[0]][rule[1]][rule[2]] = true
 default:
 }
 }
}
console.log(res)

answered Aug 30, 2018 at 15:38

1 Comment

thank you for the effort. It indeed works as intended. I have already accepted another answer, though. Sorry. upvoted though! :)
0

To do that you can use the following function:

function setIn(target, path, value) {
 var chain = String(path).split('.');
 while (chain.length > 0) {
 var field = chain.shift();
 if (chain.length == 0) {
 target[field] = value;
 } else if (field in target && target[field] !== null && typeof target[field] === 'object') {
 target = target[field];
 } else {
 target[field] = {}
 target = target[field];
 }
 }
 return value;
}

And produce the tree:

var tree = { privileges: {} };
for (var i = 0; i < array.length; i += 1)
 setIn(tree.privileges, array[i], true);
answered Aug 30, 2018 at 15:28

Comments

0

You can use Array.reduce() for this to create your nested map. The above example will work for any level of children and will always set the last child to a boolean value.

const arr = ["Module1.resource1.create","Module1.resource1.read","Module1.resource1.update","Module1.resource1.delete","Module1.resourceN.create","Module1.resourceN.read","Module1.resourceN.update","Module2.resourceN.update",];
let result = {privalages:{}};
result.privalages = arr.reduce((o, curr)=>{
 let props = curr.split(".");
 props.reduce((a, prop, index)=> a[prop] = index !== props.length-1 ?(a[prop] || {}) : true,o);
 return o;
},{});
console.log(result);

answered Aug 30, 2018 at 15:49

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.