从嵌套键的字符串构建嵌套的JSON

时间:2017-05-24 21:18:10

标签: javascript json node.js ecmascript-6

我有使用nodeJS阅读的csv文件。我在阅读之前将每个文件转换为文本。

文件中的每一行都有以'='分隔的数据。

每一行看起来像

data.location.degree.text=sometexthere

“=”之前的第一部分表示我的应用程序中json对象的索引。我的目标是解析这些数据并构建它的json表示,以便上面的行成为

data:{
  location:{
    degree:{
      text: 'sometexthere'
    }
  }
}

使用javascript / node js;如何将一个应该代表嵌套JSON键序列的字符串转换为上面的json对象?

2 个答案:

答案 0 :(得分:3)

您可以拆分路径并检查是否存在以下元素。如果没有将对象分配给新属性。

然后返回属性的值。

最后指定值。

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

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

var data = {};

setValue(data, 'location.degree.text', 'sometexthere');
console.log(data);

答案 1 :(得分:0)

// result container
var res = {};

// input data
var inp = [
    'data.location.degree.text=sometexthere',
    'data.otherLocation.degree.otherText=foo',
    'data.location.degree.otherText=bar',
    'we.can.do.undefined.values='
];

// recursive function
var pathToObject = function(resultReference, path)
{
    // split path on dots
    // e.g. data.location.degree.text=sometexthere
    // -> ["data", "location", "degree", "text=sometexthere"]
    var splitPathParts = path.split('.');

    // if there is only one part, we're at the end of our path expression
    // e.g. ["text=sometexthere"]
    if (splitPathParts.length === 1){
        // split "text=sometexthere" into ["text", "sometexthere"]
        var keyAndValue = splitPathParts[0].split('=');

        // set foo = bar on our result object reference
        resultReference[keyAndValue[0]] = keyAndValue[1];
        return;
    }
  
    // the first element of the split array is our current key
    // e.g. for ["data", "location", "degree", "text=sometexthere"],
    // the currentKey would be "data";
    var currentKey = splitPathParts.shift();

    // if our object does not yet contain the current key, set it to an empty object
    resultReference[currentKey] || (resultReference[currentKey] = {});
    
    // recursively call ourselves, passing in
    // the nested scope and the rest of the path.
    // e.g. { data : {} } and 'location.degree.text=sometexthere'
    pathToObject(resultReference[currentKey], splitPathParts.join('.'));
}

for (var i = 0; i < inp.length; i++)
{
    pathToObject(res, inp[i]);
}
console.log(res);

ES6语法使事情变得更紧凑:

'use strict';

const pathToObject = (resultReference, path) => {
  let [currentKey, ...restOfPath] = path.split('.');
  
  if (restOfPath.length === 0) {
    let [k, v] = currentKey.split('=');
    resultReference[k] = v;
    return;
  }

  resultReference[currentKey] || (resultReference[currentKey] = {});
  pathToObject(resultReference[currentKey], restOfPath.join('.'));
}

let res = {};

[
  'data.location.degree.text=sometexthere',
  'data.otherLocation.degree.otherText=foo',
  'data.location.degree.otherText=bar',
  'we.can.do.undefined.values='
].forEach(x => pathToObject(res, x));

console.log(res);