Skip to content

Commit 17cc241

Browse files
authored
Allow encoding data with missing fields. (#50)
1 parent 1349820 commit 17cc241

File tree

5 files changed

+79
-1
lines changed

5 files changed

+79
-1
lines changed

README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,25 @@ file:close()
180180
local output = ftcsv.encode(everyUser, {encodeNilAs=0}) -- for setting it to 0
181181
```
182182

183+
- `allowMissingKeys`
183184

185+
If set to a non-`nil` value, this option allows encoding data sets that are entirely missing a field that was specified in `fieldsToKeep`. Otherwise, ftcsv would raise an error.
186+
187+
```lua
188+
local data = {
189+
{a = 1, b = 2, c = 3},
190+
{a = 10, b = 20},
191+
{a = 100, c = 200},
192+
}
193+
ftcsv.encode(data, {fieldsToKeep = {"a", "b", "c", "d"}}) --> [throws an error]
194+
ftcsv.encode(data, {fieldsToKeep = {"a", "b", "c", "d"}, allowMissingKeys = true})
195+
--> [[
196+
--> "a","b","c","d"
197+
--> "1","2","3","nil"
198+
--> "10","20","nil","nil"
199+
--> "100","nil","200","nil"
200+
--> ]]
201+
```
184202

185203
## Error Handling
186204
ftcsv returns a litany of errors when passed a bad csv file or incorrect parameters. You can find a more detailed explanation of the more cryptic errors in [ERRORS.md](ERRORS.md)

ftcsv.lua

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -814,7 +814,9 @@ local function initializeGenerator(inputTable, delimiter, options)
814814
if headers == nil then
815815
headers = extractHeadersFromTable(inputTable)
816816
end
817-
validateHeaders(headers, inputTable)
817+
if options and options.allowMissingKeys == nil then
818+
validateHeaders(headers, inputTable)
819+
end
818820

819821
local escapedHeaders = escapeHeadersForOutput(headers, delimiter, options)
820822
local output = initializeOutputWithEscapedHeaders(escapedHeaders, delimiter, options)

spec/csvs/missing_keys.csv

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
a,b,c
2+
1,2,3
3+
10,20,
4+
100,,300

spec/json/missing_keys.json

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
[
2+
{
3+
"a": "1",
4+
"b": "2",
5+
"c": "3",
6+
"d": "nil"
7+
},
8+
{
9+
"a": "10",
10+
"b": "20",
11+
"c": "nil",
12+
"d": "nil"
13+
14+
},
15+
{
16+
"a": "100",
17+
"b": "nil",
18+
"c": "300",
19+
"d": "nil"
20+
21+
}
22+
]

spec/parse_encode_spec.lua

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,35 @@ describe("csv encode without quotes", function()
114114
end)
115115
end
116116
end)
117+
118+
--[[ This breaks simple_crlf.
119+
describe("csv encode with missing keys", function()
120+
for _, value in ipairs(files) do
121+
it("should handle " .. value, function()
122+
local jsonFile = loadFile("spec/json/" .. value .. ".json")
123+
local jsonDecode = cjson.decode(jsonFile)
124+
local reEncoded = ftcsv.parse(ftcsv.encode(
125+
jsonDecode, ",", {
126+
fieldsToKeep = {"a", "b", "c", "d"},
127+
allowMissingKeys = true,
128+
}
129+
), ",", {loadFromString=true})
130+
assert.are.same(jsonDecode, reEncoded)
131+
end)
132+
end
133+
end)
134+
--]]
135+
136+
describe("csv encode with missing keys", function()
137+
it("should handle missing_keys", function()
138+
local jsonFile = loadFile("spec/json/missing_keys.json")
139+
local jsonDecode = cjson.decode(jsonFile)
140+
local reEncoded = ftcsv.parse(ftcsv.encode(
141+
jsonDecode, ",", {
142+
fieldsToKeep = {"a", "b", "c", "d"},
143+
allowMissingKeys = true,
144+
}
145+
), ",", {loadFromString=true})
146+
assert.are.same(jsonDecode, reEncoded)
147+
end)
148+
end)

0 commit comments

Comments
 (0)