change string to array

问题: I retrieve the following array of string values [ "Module1.resource1.create", "Module1.resource1.read", "Module1.resource1.update", "Module1.resource1.delete", ... "Modu...

问题:

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


回答1:

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


回答2:

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

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


回答3:

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)


回答4:

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

回答5:

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

  • 发表于 2018-08-31 19:54
  • 阅读 ( 293 )
  • 分类:sof

条评论

请先 登录 后评论
不写代码的码农
小编

篇文章

作家榜 »

  1. 小编 文章
返回顶部
部分文章转自于网络,若有侵权请联系我们删除