Skip to content

Commit 50b9237

Browse files
committed
Adding comments to csv-2-json.js
Added comments to explain what code is doing.
1 parent 233c1d7 commit 50b9237

File tree

1 file changed

+45
-38
lines changed

1 file changed

+45
-38
lines changed

lib/csv-2-json.js

Lines changed: 45 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,79 +3,86 @@
33
var _ = require('underscore'),
44
async = require('async');
55

6-
var options = {};
6+
var options = {}; // Initialize the options - this will be populated when the csv2json function is called.
77

8+
// Generate the JSON heading from the CSV
89
var retrieveHeading = function (lines, callback) {
9-
if (!lines.length) {
10-
callback(new Error("No data provided to retrieve heading.")); // Error - no data
10+
if (!lines.length) { // If there are no lines passed in, then throw an error
11+
return callback(new Error("No data provided to retrieve heading.")); // Pass an error back to the user
1112
}
1213
var heading = lines[0]; // Grab the top line (header line)
1314
return heading.split(options.DELIMITER); // Return the heading split by the field options.DELIMITER
1415
};
1516

17+
// Add a nested key and its value in the given document
1618
var addNestedKey = function (key, value, doc) {
1719
var subDocumentRoot = doc, // This is the document that we will be using to add the nested keys to.
18-
trackerDocument = subDocumentRoot, // This is the document that will recur through the subDocument, starting at the Root
19-
nestedKeys = key.split('.'),
20-
finalKey = nestedKeys.pop();
20+
trackerDocument = subDocumentRoot, // This is the document that will use to iterate through the subDocument, starting at the root
21+
nestedKeys = key.split('.'), // Array of all keys and sub keys for the document
22+
finalKey = nestedKeys.pop(); // Retrieve the last sub key.
2123
_.each(nestedKeys, function (nestedKey) {
22-
if (doesKeyExist(nestedKey, trackerDocument)) { // this nestedKey already exists, use existing doc
23-
trackerDocument = trackerDocument[nestedKey];
24+
if (keyExists(nestedKey, trackerDocument)) { // This nestedKey already exists, use an existing doc
25+
trackerDocument = trackerDocument[nestedKey]; // Update the trackerDocument to use the existing document
2426
} else {
25-
trackerDocument[nestedKey] = {}; // Add document at key
26-
trackerDocument = trackerDocument[nestedKey]; // Updated subDoc to be the added doc for the nestedKey
27+
trackerDocument[nestedKey] = {}; // Add document at the current subKey
28+
trackerDocument = trackerDocument[nestedKey]; // Update trackerDocument to be the added doc for the subKey
2729
}
2830
});
29-
trackerDocument[finalKey] = value;
30-
return subDocumentRoot;
31+
trackerDocument[finalKey] = value; // Set the final layer key to the value
32+
return subDocumentRoot; // Return the document with the nested document structure setup
3133
};
3234

33-
var doesKeyExist = function (key, doc) {
34-
return (typeof doc[key] !== 'undefined');
35+
// Helper function to check if the given key already exists in the given document
36+
var keyExists = function (key, doc) {
37+
return (typeof doc[key] !== 'undefined'); // If the key doesn't exist, then the type is 'undefined'
3538
}
3639

40+
// Create a JSON document with the given keys (designated by the CSV header) and the values (from the given line)
3741
var createDoc = function (keys, line, callback) {
38-
var doc = {},
39-
val,
40-
line = line.trim().split(options.DELIMITER);
41-
if (line == '') { return false; }
42-
if (keys.length !== line.length) {
43-
callback(new Error("Not every line has a correct number of values.")); // This line doesn't have the same # vals as the header
42+
var doc = {}, // JSON document to start with and manipulate
43+
val, // Temporary variable to set the current key's value to
44+
line = line.trim().split(options.DELIMITER); // Split the line using the given DELIMITER after trimming whitespace
45+
if (line == '') { return false; } // If we have an empty line, then return false so we can remove all blank lines (falsy values)
46+
if (keys.length !== line.length) { // If the number of keys is different than the number of values in the current line
47+
return callback(new Error("Not every line has a correct number of values.")); // Pass the error back to the client
4448
}
4549
_.each(keys, function (key, indx) {
4650
val = line[indx] === '' ? null : line[indx];
47-
if (key.indexOf('.')) { // Key has '.' representing nested document
48-
doc = addNestedKey(key, val, doc); // Update the doc
49-
} else {
50-
doc[key] = val;
51+
if (key.indexOf('.')) { // If key has '.' representing nested document
52+
doc = addNestedKey(key, val, doc); // Update the document to add the nested key structure
53+
} else { // Else we just have a straight key:value mapping
54+
doc[key] = val; // Set the value at the current key
5155
}
5256
});
53-
return doc;
57+
return doc; // Return the created document
5458
};
5559

60+
// Main wrapper function to convert the CSV to the JSON document array
5661
var convertCSV = function (lines, callback) {
57-
var headers = retrieveHeading(lines, callback),
58-
jsonDocs = [];
62+
var headers = retrieveHeading(lines, callback), // Retrieve the headings from the CSV
63+
jsonDocs = []; // Create an array that we can add the generated documents to
5964
lines = lines.splice(1); // Grab all lines except for the header
60-
_.each(lines, function (line) {
65+
_.each(lines, function (line) { // For each line, create the document and add it to the array of documents
6166
jsonDocs.push(createDoc(headers, line));
6267
});
63-
return _.filter(jsonDocs, function (doc) { return doc !== false; });;
68+
return _.filter(jsonDocs, function (doc) { return doc !== false; });; // Return all non 'falsey' values to filter blank lines
6469
};
6570

6671
module.exports = {
67-
72+
73+
// Function to export internally
74+
// Takes options as a document, data as a CSV string, and a callback that will be used to report the results
6875
csv2json: function (opts, data, callback) {
69-
if (!callback) { throw new Error('A callback is required!'); }
76+
if (!callback) { throw new Error('A callback is required!'); } // If a callback wasn't provided, throw an error
7077
if (!opts) { callback(new Error('Options were not passed and are required.')); return null; } // Shouldn't happen, but just in case
71-
else { options = opts; }
72-
if (!data) { callback(new Error('Cannot call csv2json on ' + data)); return null; }
73-
if (typeof data !== 'string') { // CSV is not a string
74-
callback(new Error("CSV is not a string"));
78+
else { options = opts; } // Options were passed, set the global options value
79+
if (!data) { callback(new Error('Cannot call csv2json on ' + data + '.')); return null; } // If we don't receive data, report an error
80+
if (typeof data !== 'string') { // The data is not a string
81+
callback(new Error("CSV is not a string.")); // Report an error back to the caller
7582
}
76-
var lines = data.split(options.EOL);
77-
var json = convertCSV(lines, callback);
78-
callback(null, json);
83+
var lines = data.split(options.EOL); // Split the CSV into lines using the specified EOL option
84+
var json = convertCSV(lines, callback); // Retrieve the JSON document array
85+
callback(null, json); // Send the data back to the caller
7986
}
8087

8188
};

0 commit comments

Comments
 (0)