1

I have csv files that I am reading using nodeJS. I convert each file to text before reading.

Each line in the file have data delimited with =.

Each line looks something like

data.location.degree.text=sometexthere

The first portion before the "=" represents an index to a JSON object in my app. My aim is to parse this data and build a JSON representation of it so that the line above becomes

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

Using javascript/nodejs; How can I convert a string which is supposed to represent a sequence of nested JSON keys, into a JSON object like above?

0

2 Answers 2

10

You could split the path and make a check if the following element exist. If not assign an object to the new property.

Return then the value of the property.

At the end assign the value.

function setValue(object, path, value) {
    path = path.replace(/[\[]/gm, '.').replace(/[\]]/gm, ''); //to accept [index]
    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);

Sign up to request clarification or add additional context in comments.

4 Comments

this is elegant as ****!
@Nina Scholz I would give this a thousands thumbs up if I could. Thanks!
add path = path.replace(/[\[]/gm, '.').replace(/[\]]/gm, ''); to the top of the function to accept [n] parameter. .0 and [0] both work the same
@SwiftNinjaPro, that is right, but an edit makes in view of the question no sense.
2

// 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.handle.values.that.are_undefined=',
    'we.can.handle.values.that.contain_equals_signs=yes=we=can'
];

// 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.shift()] = keyAndValue.join('=');
        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 syntax makes things slightly more terse:

'use strict';

const pathToObject = (resultReference, path) => {
  let [currentKey, ...restOfPath] = path.split('.');
  
  if (restOfPath.length === 0) {
    let [k, ...v] = currentKey.split('=');
    resultReference[k] = v.join('=');
    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.handle.values.that.are_undefined=',
  'we.can.handle.values.that.contain_equals_signs=yes=we=can'
].forEach(x => pathToObject(res, x));

console.log(res);

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.