JavaScript:对象转换

时间:2018-06-22 08:46:55

标签: javascript

我想将一个对象(输入)变成另一个(输出)。

例如,我得到了这个输入对象:

var input = {
    'person1.name': 'John',
    'person1.address.street': 'main street',
    'person1.address.zipcode': 12345,
    'person2.name': 'Smith',
    'person2.address.street': 'major street',
    'person2.address.zipcode': 12345
}

var output = {
    person1: {
        name: 'John',
        address: {
            street: 'Main Street',
            zipcode: 12345
        }
    },
    person2: {
        name: 'Smith',
        address: {
            street: 'Major Street',
            zipcode: 12345
        }
    }
}

我正在尝试做类似的事情,但未能完成:

const input= getInputValue();
const output = {};

for (let prop in input) {
  let arr = prop.split('.');
  arr.forEach(el => {
    output[el] = output 
  })
}

4 个答案:

答案 0 :(得分:2)

如果使用lodash,这非常简单。

参考:lodash _.set函数

var input = {
  'person1.name': 'John',
  'person1.address.street': 'main street',
  'person1.address.zipcode': 12345,
  'person2.name': 'Smith',
  'person2.address.street': 'major street',
  'person2.address.zipcode': 12345
}

var output = {};

for (let prop in input) {
  _.set(output, prop, input[prop]);
}

console.log(output);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>

答案 1 :(得分:1)

您可以使用函数将路径拆分为值并为其生成新对象。

function setValue(object, path, value) {
    var last = path.pop();

    path.reduce((o, k) => o[k] = o[k] || {}, object)[last] = value;
    return object;
}

var input = { 'person1.name': 'John', 'person1.address.street': 'main street', 'person1.address.zipcode': 12345, 'person2.name': 'Smith', 'person2.address.street': 'major street', 'person2.address.zipcode': 12345 },
    output = {};

Object
    .entries(input)
    .forEach(([k, v]) => setValue(output, k.split('.'), v));

console.log(output);
.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 2 :(得分:0)

这是基于您提供的forEach循环的另一种解决方案。

它使用parent对将存储属性的对象的引用:

  • 如果el是数组中的最后一个,它将向父对象添加属性
  • 如果不是,它将在树中创建一个新对象
  • 循环之前,将parent引用设置为在树中创建的新对象。

var input = {
    "person1.name": 'John',
    "person1.address.street": 'main street',
    "person1.address.zipcode": 12345,
    "person2.name": 'Smith',
    "person2.address.street": 'major street',
    "person2.address.zipcode": 12345
}

const output = {};

for (let prop in input) {
  let arr = prop.split('.');
  let parent = output;
  arr.forEach((el, index) => {
    
    if (index === arr.length -1) {
      // el is a leaf, time to add the value of the property in the parent 
      parent[el] = input[prop];     
    } else {
      // el is not a leaf, create a node in the tree if it doesn't already exist
      parent[el] = parent[el] || {};
    }
    
    // moving down the tree 
    parent = parent[el];
  })
}

console.log(output);

答案 3 :(得分:0)

此示例无需更改原始对象即可完成您需要的操作

您可以使用递归并遍历keys数组,直到到达结尾为止:

https://jsfiddle.net/5ykbLpav/68/

var input = {
    'person1.name': 'John',
    'person1.address.street': 'main street',
    'person1.address.zipcode': 12345,
    'person2.name': 'Smith',
    'person2.address.street': 'major street',
    'person2.address.zipcode': 12346
}

function buildTree(obj, keys, val) {
  let key = keys[0]
  if (keys.length === 1) {
    obj[key] = val
    return obj
  } else {
    let nKeys = keys.slice().splice(1, keys.length)
    // or if you are okay with mutation you could just do --> keys.shift()
    let node = {};
    if (obj[key]) {
        node = obj[key]
    } 
    obj[key] = buildTree(node, nKeys, val)
    return obj
  }
}


function cleanObject(obj) {
  return Object.keys(obj).reduce((acc, curr) => {
    let keys = curr.split('.')
    return buildTree(acc, keys, obj[curr])
  }, {})
}

let cleanObj = cleanObject(input)
console.log(cleanObj)