How the CSV is read
The converter reads the text the way CsvHelper's CsvParser does with its default settings, which follow RFC 4180:
- A field that starts with
"is quoted: it runs to the closing quote and may contain the delimiter and line breaks.""inside it is one quote. - Records end at
\r\n,\nor\r. Blank lines are skipped (IgnoreBlankLines), but a line with only spaces is a record. - Spaces are kept:
astaysa. CsvHelper only trims withTrimOptions.Trim. - A byte order mark at the start of a file is dropped, as
StreamReaderdoes.
With a header row, each record becomes an object. A row with fewer fields than the header gets null for the missing ones, and fields beyond the header are left out (the page counts both). Without a header row, each record becomes an array.
Delimiter detection
With DetectDelimiter = true, CsvHelper looks at the first 4,096 characters, removes everything between quotes, and counts , ; | and tab on each line. The last line is ignored when there is more than one, because it may be cut off. A delimiter must appear on every line and the most frequent one wins, but when two or more lines are counted, a comma on every one wins outright (it is the invariant culture's list separator). With a single line and no candidate on it, the comma stays.
Numbers, booleans and null
CSV has only text. With "Numbers, booleans and null" on, a value becomes a JSON value when it is unambiguous:
| CSV value | JSON |
|---|---|
| 42, -1.50, 1e3 | 42, -1.50, 1e3 (numbers, as written) |
| true, True, TRUE | true |
| (empty), null | null |
| 007, 1,5, +1, 1. | "007", "1,5", "+1", "1." (strings) |
Numbers keep their text, so 1.50 is not rounded to 1.5 and long IDs are not cut to double precision. Turn the option off to get every value as a string.
Bad data: stray quotes
A quote in the middle of an unquoted field (Marko "Mare") or text after a closing quote ("Ivan" Petrović) breaks RFC 4180. CsvHelper's default BadDataFound throws a BadDataException when it reads such a field, and so does this page. With BadDataFound = null the field is read anyway: an unquoted one as it is, a quoted one without its quotes. The CSV viewer highlights every bad field and every row with the wrong number of fields. To go back from JSON, use the JSON to CSV converter.
Convert CSV to JSON in C#
The code follows the settings above (it needs the CsvHelper NuGet package) and gives the same JSON as this page:
using System.Globalization;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.RegularExpressions;
using CsvHelper;
using CsvHelper.Configuration;
static string CsvToJson(string path)
{
var config = new CsvConfiguration(CultureInfo.InvariantCulture)
{
DetectDelimiter = true, // tries , ; | and tab
};
using var reader = new StreamReader(path); // drops a UTF-8 BOM
using var parser = new CsvParser(reader, config);
var rows = new JsonArray();
string[]? header = null;
while (parser.Read())
{
var record = parser.Record!;
if (header == null)
{
header = record;
continue;
}
var row = new JsonObject();
for (var i = 0; i < header.Length; i++)
row[header[i]] = i < record.Length ? ToJson(record[i]) : null;
rows.Add(row);
}
return rows.ToJsonString(new JsonSerializerOptions
{
WriteIndented = true,
NewLine = "\n", // .NET 9+; the default is Environment.NewLine
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, // keep é, <, > and & as they are
});
}
// "" and "null" become null, true/false booleans, and JSON numbers stay numbers as written.
// "007" and "1,5" are not JSON numbers, so they stay strings.
static JsonNode? ToJson(string value) => value switch
{
"" or "null" => null,
"true" or "True" or "TRUE" => true,
"false" or "False" or "FALSE" => false,
_ when Regex.IsMatch(value, @"^-?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)?\z") => JsonNode.Parse(value),
_ => value,
};
Tested with CsvHelper 33.1 on .NET 10. On .NET 8, leave out NewLine and IndentSize. When the CSV maps to a class of your own, csv.GetRecords<Product>() on a CsvReader converts the types for you, and JsonSerializer.Serialize writes the list.
FAQ
How do I convert CSV to JSON in C#?
Read the file with CsvHelper's CsvParser, take the first record as the header, build a JsonObject for every other record and add it to a JsonArray, then call ToJsonString. The C# on this page does that and gives the same JSON as the converter.
How does CsvHelper detect the delimiter?
With DetectDelimiter = true it looks at the first 4,096 characters, removes quoted text, and counts comma, semicolon, pipe and tab on each line except the last. Only a character found on every line counts and the most frequent one wins, but when two or more lines are counted, a comma on every one wins outright.
What is BadDataException?
CsvHelper throws it when a field breaks RFC 4180 quoting: a quote inside an unquoted field, or text after the closing quote of a quoted field. Set BadDataFound = null to read such fields as they are, or collect them in a callback.
Why is 007 still a string in the JSON?
Only values that are valid JSON numbers become numbers. 007, 1,5 and +1 are not, so they stay strings and zip codes or IDs with leading zeros are not changed.
Is my CSV uploaded?
No. The converter runs in your browser, and files you open or drop are read locally.