NDJSON to matrix

Paste newline-delimited JSON and get one rectangular table: nested objects flattened to dotted columns, the union of every path as the header, missing cells filled the way you choose, and CSV, TSV, an aligned grid or a JSON array of rows out.

Try:
Matrix

About this tool

NDJSON (also called JSON Lines or JSONL) is great for logs and streams because each line is a complete JSON record. It is less convenient when you need a rectangular table: one record may have user.tier, the next may omit it, and nested payloads can hide the numeric columns you actually want.

This tool parses each non-blank line independently, flattens nested objects into column paths such as user.geo.lat, takes the union of every path it sees, and writes one aligned row per record. Missing paths and JSON null become your chosen fill value, so ragged event streams become CSV, TSV, a whitespace-aligned matrix, or a JSON array of rows without writing a script.

Worked example

Input:

{"id":1,"latency_ms":12,"user":{"tier":"pro"}}
{"id":2,"latency_ms":940}
{"id":3,"latency_ms":31,"user":{"tier":"free"}}

With the defaults (format=csv, headers on, first-seen columns, blank fill) the output is:

id,latency_ms,user.tier
1,12,pro
2,940,
3,31,free

Turn on Numeric columns only, set Fill for missing cells to 0, and turn headers off when you need a bare numeric matrix for numpy.loadtxt, R, Octave, or a plotting package. Use Columns to keep when you want a stable schema in a specific order.

Controls that matter

Limits and edge cases

FAQ

What is the difference between NDJSON and a JSON array?

NDJSON has one complete JSON value per line: {...}\n{...}\n{...}. A JSON array wraps all records in one value: [{...},{...}]. This tool expects NDJSON because that is how logs, export streams and append-only data files are usually stored. If you have one big JSON array, split it into one element per line first.

How are nested objects and arrays turned into columns?

Object keys are joined with the path separator. With the default separator, {"user":{"id":7}} becomes column user.id. Arrays default to indexed columns, so {"v":[10,20]} becomes v.0 and v.1; switch Nested arrays to JSON to keep [10,20] in one cell, or to skip to drop array-valued data entirely.

How do I make a numeric matrix with no labels?

Set Numeric columns only on, choose a fill such as 0 or NaN, and turn Include the header row off. The matrix format produces a whitespace-aligned grid, while CSV/TSV produce delimiter-separated rows that common numeric tools can load.

What happens when one line is not valid JSON?

With Unparsable lines: error, conversion stops and the error names the line number and parser location. With skip, malformed lines are ignored and the remaining records are converted. If every non-blank line is invalid, the tool still returns an error instead of emitting an empty table.

Can I force a schema instead of using every discovered column?

Yes. Put a comma-separated list in Columns to keep, such as timestamp, latency_ms, user.tier. The output uses exactly that order and fails if a requested path is absent, so typos do not silently produce empty columns.

Developer & Automation Access

Run it from the terminal

Same engine as this page, headless — via the gizza CLI:

gizza tool ndjson-to-matrix '{"id":1,"latency_ms":12,"user":{"tier":"pro"}}
{"id":2,"latency_ms":940}'

New to the CLI? Get gizza →

Open it by URL

Pre-fill and auto-run this tool with query parameters — the names match the API/CLI:

https://gizza.ai/tools/ndjson-to-matrix/?data=%7B%22id%22%3A1%2C%22latency_ms%22%3A12%2C%22user%22%3A%7B%22tier%22%3A%22pro%22%7D%7D%0A%7B%22id%22%3A2%2C%22latency_ms%22%3A940%7D&format=csv&delimiter=comma&separator=.&arrays=index&columns=latency_ms%2C%20user.tier&column_order=first-seen&fill=0&headers=true&row_index=true&numeric_only=true&transpose=true&max_depth=0&limit=0&invalid=error

Machine-readable descriptor: tool.json — title + parameters JSON Schema for agents.