diff --git a/README.md b/README.md index 59db1ed..b55f946 100644 --- a/README.md +++ b/README.md @@ -200,6 +200,15 @@ file:close() --> ]] ``` +- `headers` + +If set to `false` it only outputs the data without the headers. This is useful +for streaming CSV in chunks, by outputting the header first (e.g., using an +empty table), and then one or more rows of data in a loop. + +To ensure a correct data layout, this option must be used with `fieldsToKeep` +set to a constant ordering throughout the loop. + ## Error Handling 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) diff --git a/ftcsv.lua b/ftcsv.lua index 5a0690d..afd55a2 100644 --- a/ftcsv.lua +++ b/ftcsv.lua @@ -828,8 +828,21 @@ function ftcsv.encode(inputTable, delimiter, options) local delimiter, options = determineArgumentOrder(delimiter, options) local output, headers = initializeGenerator(inputTable, delimiter, options) + local offset + if (options or {}).headers == false then + if #(options.fieldsToKeep or {}) == 0 then + error( + "`fieldsToKeep` must be specified if generating a CSV " .. + "without a header." + ) + end + output = {} + offset = 0 + else offset = 1 end + for i, line in csvLineGenerator(inputTable, delimiter, headers, options) do - output[i+1] = line + -- Overwrite header with first line if headers is false + output[i + offset] = line end -- combine and return final string diff --git a/spec/csvs/no_header.csv b/spec/csvs/no_header.csv new file mode 100644 index 0000000..e2d4d2b --- /dev/null +++ b/spec/csvs/no_header.csv @@ -0,0 +1,5 @@ +"E350",3000.00,1997 +"Venture ""Extended Edition""",4900.00,1999 +"Grand Cherokee",4799.00,1996 +"Venture ""Extended Edition, Very Large""",5000.00,1999 +"Venture ""Extended Edition""",4900.00, diff --git a/spec/parse_encode_spec.lua b/spec/parse_encode_spec.lua index ba54d49..139b664 100644 --- a/spec/parse_encode_spec.lua +++ b/spec/parse_encode_spec.lua @@ -128,3 +128,20 @@ describe("csv encode with missing keys", function() assert.are.same(jsonDecode, reEncoded) end) end) + + +describe("csv encode with selective omissions", function() + local jsonFile = loadFile("spec/json/correctness.json") + local jsonDecode = cjson.decode(jsonFile) + + it("should output only data in a specific order", function() + local reEncoded = ftcsv.parse(ftcsv.encode( + jsonDecode, ",", { + fieldsToKeep = {"Model", "Price", "Year"}, + headers = false, + } + ), ",", {loadFromString=true, headers=false}) + local exp = ftcsv.parse("spec/csvs/no_header.csv", {headers = false}) + assert.are.same(exp, reEncoded) + end) +end)