1

I need to convert a large CSV data set to JSON, however the output should be a JSON dictionary like this:

var products = {
    "crystal": {
        "description": "This is a crystal",
        "price": "2.95"
    },
    "emerald": {
        "description": "This is a emerald",
        "price": "5.95"
    }
};

This is what the CSV table would look like: enter image description here

I am using a script referenced here to generate the JSON:

var csv = require('csv')
var fs = require('fs')
var f = fs.createReadStream('Fielding.csv')
var w = fs.createWriteStream('out.txt')

w.write('[');

csv()
.from.stream(f, {columns:true})
.transform(function(row, index) {
    return (index === 0 ? '' : ',\n') + JSON.stringify(row);
})
.to.stream(w, {columns: true, end: false})
.on('end', function() {
     w.write(']');
     w.end();
 });

However the output from that script is created in this format:

[
    {
        "name": "crystal",
        "description": "This is a crystal",
        "price": "2.95"
    },
    {
        "name": "emerald",
        "description": "This is a emerald",
        "price": "5.95"
    }
]

How would I modify the script to get my desired "dictionary" format?

Community
  • 1
  • 1
docta_faustus
  • 2,383
  • 4
  • 30
  • 47

5 Answers5

2

All you need to do is loop over the array and use item.name as key for your dictionary object

var products ={};

data.forEach(function(item){
     products[item.name] = item;
});

This will leave the name property in the item but that shouldn't be an issue

charlietfl
  • 170,828
  • 13
  • 121
  • 150
2

I found csv parser library most useful:

var csvText=`status,path,name,ext,checksum,size,document_service_id,document_service_path,message
success,./15-02-2017_17-11/d77c7886-ffe9-40f2-b2fe-e68410d07891//expE1.txt,expE1.txt,txt,38441337865069eabae7754b29bb43e1,414984,8269f7e3-3221-49bb-bb5a-5796cf208fd1,/neuroinftest/20170215/expE1.txt,
success,./15-02-2017_17-11/d77c7886-ffe9-40f2-b2fe-e68410d07891//expE10.txt,expE10.txt,txt,f27e46979035706eb0aaf58c26e09585,368573,2c94ed19-29c9-4660-83cf-c2148c3d6f61,/neuroinftest/20170215/expE10.txt,
success,./15-02-2017_17-11/d77c7886-ffe9-40f2-b2fe-e68410d07891//expE2.txt,expE2.txt,txt,e1040d9546423c823944120de0e5c46c,333308,b3898f5d-1058-4cf3-acf9-76759117b810,/neuroinftest/20170215/expE2.txt,
`
var csv = require('csv');
csv.parse(csvText, {columns: true}, function(err, data){
    console.log(JSON.stringify(data, null, 2));
});

In variable csvText I have my comma-separated file, with the first line serving as a header. I use the parse function and I'm passing the {columns: true} to indicated that the first line has the headers. Second parameter in the callback function (data) has the object with keys being the headers and the values being the corresponding csv cells. I use JSON.stringify to print it nicely and the result object looks like this (it puts it into an array):

[
  {
    "status": "success",
    "path": "./15-02-2017_17-11/d77c7886-ffe9-40f2-b2fe-e68410d07891//expE1.txt",
    "name": "expE1.txt",
    "ext": "txt",
    "checksum": "38441337865069eabae7754b29bb43e1",
    "size": "414984",
    "document_service_id": "8269f7e3-3221-49bb-bb5a-5796cf208fd1",
    "document_service_path": "/neuroinftest/20170215/expE1.txt",
    "message": ""
  },
  {
    "status": "success",
    "path": "./15-02-2017_17-11/d77c7886-ffe9-40f2-b2fe-e68410d07891//expE10.txt",
    "name": "expE10.txt",
    "ext": "txt",
    "checksum": "f27e46979035706eb0aaf58c26e09585",
    "size": "368573",
    "document_service_id": "2c94ed19-29c9-4660-83cf-c2148c3d6f61",
    "document_service_path": "/neuroinftest/20170215/expE10.txt",
    "message": ""
  },
  {
    "status": "success",
    "path": "./15-02-2017_17-11/d77c7886-ffe9-40f2-b2fe-e68410d07891//expE2.txt",
    "name": "expE2.txt",
    "ext": "txt",
    "checksum": "e1040d9546423c823944120de0e5c46c",
    "size": "333308",
    "document_service_id": "b3898f5d-1058-4cf3-acf9-76759117b810",
    "document_service_path": "/neuroinftest/20170215/expE2.txt",
    "message": ""
  }
]

UPD: This array can easily be turned into the object you need with reduce:

var res_obj = data.reduce(function(acc, cur, i) {
  acc[cur.name] = cur;
  return acc;
}, {});

In my case I use the name property as a key. Make sure it's unique.

ganqqwerty
  • 1,894
  • 2
  • 23
  • 36
1

I think something like this would work :

var products_arr = [{"name":"crystal","description":"This is a crystal","price":"2.95"},
 {"name":"emerald","description":"This is a emerald","price":"5.95"}]
var products = {};

for (var i = 0, l = products_arr.length ; i < l ; ++i) {
    var x = products_arr[i];
    var name = x.name
    delete x.name; // deletes name property from JSON object
    products[name] = x;
}

This will output :

{
  "crystal": {
    "description": "This is a crystal",
    "price": "2.95"
  },
  "emerald": {
    "description": "This is a emerald",
    "price": "5.95"
  }
}
John Pink
  • 607
  • 5
  • 14
  • 1
    This answer starts from the incorrect output generated by the OP's current script. However, the OP is asking how they would modify their original node code which reads the csv. – Phil Oct 28 '15 at 21:33
0

If you would like to modify your specific code, you could change the line

 return (index === 0 ? '' : ',\n') + JSON.stringify(row);

to

 var clonedRow = JSON.parse(JSON.stringify(row));
 var key = clonedRow['name'];
 delete clonedRow['name'];
 var newRow = {};
 newRow[key] = clonedRow;
 return (index === 0 ? '' : ',\n') + JSON.stringify(newRow);

This creates a new object for each row, modifying the structure according to your requirement.

Balint Domokos
  • 1,021
  • 8
  • 12
-1

Your best bet is to use PapaParse, a powerful csv parser/dumper. It supports streams, various string encodings, header row, and it's fast.

François Zaninotto
  • 7,068
  • 2
  • 35
  • 56
  • all this does is provide a library link, doesn't provide code to solve issue using that library. This *answer* is really nothing more than a comment – charlietfl Oct 28 '15 at 21:24