admin管理员组

文章数量:1389768

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:

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?

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:

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?

Share Improve this question edited May 23, 2017 at 11:53 CommunityBot 11 silver badge asked Oct 28, 2015 at 21:01 docta_faustusdocta_faustus 2,8695 gold badges32 silver badges51 bronze badges 5
  • 3 Not sure how you even ended up with that structure since columns, and thus property names, are normally the same – charlietfl Commented Oct 28, 2015 at 21:08
  • 1 Please edit your question to include a sample of the actual CSV data you're working with. – Jordan Running Commented Oct 28, 2015 at 21:08
  • Is there some kind of pattern in the names of the product, like productX where X is a number, or is it pretty random ? – John Pink Commented Oct 28, 2015 at 21:10
  • Sorry - edited. Essentially the "name" column would go away and the name value bees the name of the object. – docta_faustus Commented Oct 28, 2015 at 21:14
  • 1 just iterate array and pass item.name as property key in new object – charlietfl Commented Oct 28, 2015 at 21:15
Add a ment  | 

5 Answers 5

Reset to default 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

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 ma-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.

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"
  }
}

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.

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

本文标签: javascriptConvert CSV file to JSON dictionaryStack Overflow