# CSV to NDJSON

> Convert CSV to NDJSON: one JSON object per line, header row as keys, quoted newlines escaped so each record stays on a single line.

Source: https://devplain.com/csv-to-ndjson/
Last updated: 2026-10-30

Convert CSV to NDJSON: one JSON object per line, header row as keys, quoted newlines escaped so each record stays on a single line.

## How It Works

NDJSON, also called JSON Lines, stores one JSON object per line with no wrapping array and no commas between records. Converting CSV to NDJSON keeps the header row as the key list and writes each data row as its own compact object, which is the shape most log pipelines, stream processors and command-line tools such as jq expect.

**How a row becomes a line.** The CSV is parsed into a matrix of cells first, following RFC 4180, so a quoted field may contain the delimiter, a doubled quote or a line break. The header row is zipped onto each body row by position, the resulting object is serialised without any spaces, and a single line feed is written after it. Because objects are emitted one at a time, the output is append-friendly: concatenating two NDJSON files yields valid NDJSON, which is not true of two JSON arrays.

**Why the one-line rule holds.** A newline inside a quoted CSV field is real data, and it would break the format if it were copied through literally. The serialiser escapes it as \n inside the JSON string, so the value survives while the record still occupies exactly one physical line. Reading the result back with a line-based tool gives the same value the CSV contained.

**Line endings and blank lines.** Output always uses LF, even when the input arrived with Windows CRLF endings, so a mixed batch produces consistent files. Blank lines in the CSV are skipped rather than turned into empty objects, and a trailing newline at the end of the input does not create a final empty record.

**What the values look like.** Every value is a string, because CSV carries no type information and converting eagerly would damage identifiers such as 0042. A row with fewer cells than the header gets null for the missing columns, and a repeated header name is suffixed _2 rather than overwriting the first column. A header-only file produces no lines at all, and empty input is reported as an error rather than silently returning nothing.

**Where it is used.** Bulk imports into BigQuery, Elasticsearch and ClickHouse, log shipping, and test fixtures that need to stream one record at a time are the common cases. If you need a single JSON array instead, the CSV to JSON page produces that; the two outputs hold the same data in different envelopes.

The conversion runs in the tab, so a customer export never leaves the browser.

### How to convert a CSV file to NDJSON

1. Paste the CSV with its header row first, and check the delimiter matches the file.
2. Confirm the direction selector reads CSV to NDJSON.
3. Read the output as one object per line; each line is complete and ends with a line feed.
4. Save the result with a .ndjson or .jsonl extension so downstream tools treat it as JSON Lines.

### CSV input and the NDJSON it produces

| CSV input | NDJSON output | Rule |
| --- | --- | --- |
| Header plus two data rows | Two objects, one per line, LF after each | Header names the keys; no outer array |
| A quoted field containing a newline | One object, with \n escaped inside the string | The record stays on one physical line |
| CRLF line endings | LF line endings | Output endings are normalised |
| Header row only | No output at all | There are no records to write |

## Examples

### Input

```
name,age
Alice,30
Bob,25
```

### Output

```
{"name":"Alice","age":"30"}
{"name":"Bob","age":"25"}
```

Two rows become two complete objects, each followed by a single line feed.

### Input

```
desc,age
"a
b",1
```

### Output

```
{"desc":"a\nb","age":"1"}
```

Boundary case: a newline inside a quoted field is escaped, so one record is still exactly one line.

### Input

```
a,b
1,2
```

### Output

```
{"a":"1","b":"2"}
```

Boundary case: Windows CRLF input and a trailing blank line produce one LF-terminated record.

### Input

```
a,b

1,2

3,4
```

### Output

```
{"a":"1","b":"2"}
{"a":"3","b":"4"}
```

Blank lines are skipped instead of becoming empty objects.

### Input

```
name,age
```

### Output

```

```

Boundary case: a header with no data rows yields no output at all, because there are no records to write.

## Frequently Asked Questions

**What is NDJSON and how is it different from a JSON array?**

NDJSON writes one JSON object per line and no brackets or commas between records; a JSON array wraps everything in "[" and "]" with commas. NDJSON can be appended to, split and read line by line without parsing the whole file, which is why log pipelines prefer it. Both forms hold the same objects.

**What happens if a CSV field contains a newline?**

It is escaped as \n inside the JSON string, so the record still occupies one line. Splitting the output by newline therefore never cuts an object in half, and reading the value back returns the original multi-line text. Copying the newline through literally would produce two malformed half-records instead.

**Are numbers and booleans typed in the output?**

No. Every value is a string, because CSV carries no type information and eager conversion would corrupt identifiers such as 0042 or long account numbers. Cast the fields you need after loading the records, where you know which columns are numeric. A missing cell becomes null rather than an empty string.

**Why is the output empty for a header-only file?**

Because the header names the keys and contains no data. With zero body rows there is nothing to serialise, so the result is an empty string rather than an empty line or an empty array. Empty input is different: it is rejected with the error Empty CSV input.

## Limitations & Accuracy

Every value is emitted as a string, so numbers and booleans need casting after import. Output line endings are always LF, even from a CRLF file, and a header-only file produces an empty string rather than an empty array. A row with fewer cells than the header gets null for the missing columns, and a repeated header is suffixed _2. Only comma, semicolon and tab delimiters are offered, empty input returns an error, and very large files are limited by browser memory.

## Related Tools

- [CSV to JSON Converter](https://devplain.com/csv-to-json/)
- [Convert CSV to JSON with Header Row](https://devplain.com/convert-csv-to-json-with-header-row/)
- [All tools](https://devplain.com/tools/)

Last updated: 2026-10-30

