Skip to content

Commit c934d78

Browse files
committed
CSV support nested fields
1 parent 461bf40 commit c934d78

File tree

2 files changed

+63
-30
lines changed

2 files changed

+63
-30
lines changed

spec/csv.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,23 @@
1-
/* global tocsv */
1+
/* global tocsv, flatten */
22

33
assert.that('CSV constructor should have a name', function(c) {
44
assert.eq(tocsv([{a:1}]).constructor.name, 'CSV')
55
})
6+
7+
assert.that('CSV first line contains field names', function(c) {
8+
assert.eq(tocsv([{a:1}]).lines[0], 'a')
9+
assert.eq(tocsv([{a:1, b: 2}]).lines[0], 'a,b')
10+
})
11+
12+
assert.that('CSV documents could have different fields', function(c) {
13+
assert.eq(tocsv([{a:1}, {b:2}]).lines[0], 'a,b')
14+
assert.eq(tocsv([{a:1}, {b:2}]).lines[1], '1,')
15+
assert.eq(tocsv([{a:1}, {b:2}]).lines[2], ',2')
16+
})
17+
18+
assert.that('CSV support nested fields', function(c) {
19+
assert.eq(tocsv([{a:{b:2}}]).lines[0], 'a.b')
20+
assert.eq(tocsv([{a:{b:2}}]).lines[1], '2')
21+
assert.eq(tocsv([{a:{b:2,c:3}}]).lines[0], 'a.b,a.c')
22+
assert.eq(tocsv([{a:{b:2,c:3}}]).lines[1], '2,3')
23+
})

src/csv.js

Lines changed: 44 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -47,35 +47,50 @@ var printcsv = function(x) {
4747
})
4848
}
4949

50-
var tocsv = function(x) {
51-
var lines = [],
52-
fieldNames = {},
53-
encodedDocuments = x.map(function(doc) {
54-
return _.reduce(doc, function(values, value, field) {
55-
fieldNames[field] = true
56-
values[field] = tojson(value).replace(
57-
/^(?:ISODate|ObjectId)\((.*)\)$/,
58-
function(_, contentAsString) {
59-
return contentAsString
60-
}
61-
)
62-
return values
63-
}, {})
64-
})
50+
var tocsv = (function() {
51+
var flatten = function(o) {
52+
return _.reduce(o, function(flattened, value, field) {
53+
if (_.isPlainObject(value)) {
54+
_.forEach(flatten(value), function(nestedValue, nestedField) {
55+
flattened[[field, nestedField].join('.')] = nestedValue
56+
})
57+
} else {
58+
flattened[field] = value
59+
}
60+
return flattened
61+
}, {})
62+
}
6563

66-
fieldNames = _.keys(fieldNames)
64+
return function(x) {
65+
var lines = [],
66+
fieldNames = {},
67+
encodedDocuments = x.map(function(doc) {
68+
return _.reduce(flatten(doc), function(values, value, field) {
69+
fieldNames[field] = true
70+
values[field] = tojson(value).replace(
71+
/^(?:ISODate|ObjectId)\((.*)\)$/,
72+
function(_, contentAsString) {
73+
return contentAsString
74+
}
75+
)
76+
return values
77+
}, {})
78+
})
6779

68-
lines.push(fieldNames.join(','))
69-
encodedDocuments.forEach(function(encodedDocument) {
70-
lines.push(
71-
fieldNames.map(function(fieldName) {
72-
if (encodedDocument[fieldName] !== undefined) {
73-
return encodedDocument[fieldName]
74-
}
75-
return '""'
76-
}).join(',')
77-
)
78-
})
80+
fieldNames = _.keys(fieldNames)
7981

80-
return new CSV(lines)
81-
}
82+
lines.push(fieldNames.join(','))
83+
encodedDocuments.forEach(function(encodedDocument) {
84+
lines.push(
85+
fieldNames.map(function(fieldName) {
86+
if (encodedDocument[fieldName] !== undefined) {
87+
return encodedDocument[fieldName]
88+
}
89+
return ''
90+
}).join(',')
91+
)
92+
})
93+
94+
return new CSV(lines)
95+
}
96+
})()

0 commit comments

Comments
 (0)