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

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

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

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)

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);

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);

Comments

Your Answer

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.