メインコンテンツへ移動

Markdown Table to JSON

This converter turns a GitHub-flavoured Markdown table into a JSON array of records in your browser. The header row supplies the keys, cells are trimmed, and types are inferred: numbers, booleans and null, with empty cells mapping to null. Escaped pipes are decoded, the separator row is required, and nothing is uploaded.

端末内で処理

このツールの画面は英語表記です。

以下の解説は英語のみでご覧いただけます。

Markdown Table to JSON explained

Markdown tables are how READMEs, documentation and issue trackers present records; JSON is how scripts consume them. A table is already rows and columns, so the conversion is mostly about naming the columns and deciding what each cell means. This converter parses GitHub-flavoured Markdown tables into a JSON array of records — one object per body row, keys taken from the header.

The part that needs care is typing. A Markdown cell is just text, but JSON has numbers, booleans and null, and a table full of "42" strings is rarely what anything downstream wants. This converter infers: digits become numbers, true and false become booleans, empty cells become null. Inference is occasionally surprising, so the rules — leading-zero zip codes included — are written out below rather than left as a trap.

Everything runs in this browser tab: your table is parsed by an in-page engine, the JSON is serialised beside it, and no request of any kind is made — open DevTools and watch the Network panel stay empty while you convert.

Tables flow the other way just as often — when a JSON export has to land inside documentation, the JSON to Markdown table converter emits GitHub-flavoured tables with pipe escaping applied for you.

If the JSON side of the exchange is the less familiar half, the site's plain-English guide to JSON covers objects, arrays and types from first principles.

How the conversion actually works

GitHub-flavoured Markdown defines a table as three parts: a header row of column names, a delimiter row of hyphens, and zero or more body rows. The delimiter row is not decoration — in GFM it is what makes the preceding line a table at all. The converter walks the parts in order:

  • Normalise: leading and trailing pipes are optional in GFM and tolerated here; whitespace around each cell is trimmed before anything else happens.
  • Split: cells are split on unescaped pipes; a backslashed pipe (\|) becomes a literal | character inside the value.
  • Map: the header row supplies the object keys in column order, and every body row becomes one object with those keys.
  • Coerce: each trimmed cell is inferred as a number, a boolean or null; everything else stays a string — including any cell wrapped in double quotes, which opts out of inference.

Type inference, stated plainly

A table cell has no type system, so the converter has to pick one, and honesty means saying where it will bite. The rules apply to the trimmed cell text, in this order:

The last two rows are the famous one. A zip code, phone number or product code typed bare becomes a number, and a leading zero cannot survive the trip. To keep a value literal, wrap the cell in double quotes in the Markdown and the converter keeps it a string. The trade-off is deliberate: string-everything would spare the zip code and quietly break every consumer expecting real numbers.

Cell contentJSON value
42the number 42
-3.5the number -3.5
true / falsethe booleans true and false
nullnull
(empty cell)null
"02134"the string "02134" — quotes opt out
02134the number 2134 — the leading zero is gone

What the output looks like

The worked example below is the exact pair the Load sample button produces: a four-column table with a number, a boolean and an empty cell. The empty notes cell on the second record becomes an explicit null rather than an empty string, so the distinction the table author made survives into the JSON. The output is pretty-printed with two spaces to keep diffs readable.

Edges this converter refuses rather than mangles

Two malformed inputs get a named error instead of a guessed output, because each would otherwise produce records that lie:

  • No delimiter row — in GFM, a line of pipes with no row of hyphens beneath it is a paragraph, not a table. With no delimiter there is nothing to trust as a header, so the converter refuses and names the line where it looked.
  • A row wider than the header — extra cells have no key to live under, and GFM itself quietly ignores the excess. Dropping data silently is worse than an error, so the converter reports the offending row number instead. Shorter rows are padded with null, which keeps every record the same shape.

Frequently asked questions

Does converting a Markdown table to JSON upload my data anywhere?

No. Parsing and serialisation both happen inside this browser tab, in JavaScript that loaded with the page. There is no upload endpoint in the page's code, and the site's Content-Security-Policy blocks outbound connections, so the page cannot phone home even by accident. Verify it in seconds: open DevTools, watch the Network panel, convert — no request appears.

Why is the separator row of hyphens required?

In GitHub-flavoured Markdown, the delimiter row (| --- | --- |) is what turns two lines of pipes into a table; without it the text is just a paragraph containing pipes. Because the header above supplies the JSON keys, a missing separator leaves nothing trustworthy to use as a schema, so the converter rejects the input and names the line. Alignment colons such as :---: are tolerated.

How do I put a literal pipe character inside a cell?

Escape it with a backslash: \| inside a cell becomes a single | in the JSON string. That is a GFM rule, not a converter preference — an unescaped pipe would be read as a column separator and shift every cell after it. The reverse converter applies the same escaping when writing tables, so a value with a pipe survives a round trip unchanged.

What happens to values with leading zeros, like a zip code?

A bare 02134 infers as the number 2134, because JSON numbers cannot represent a leading zero. The converter makes no silent exception for zip codes, phone numbers or SKU codes — it states the rule instead. To keep a value textual, wrap the cell in double quotes in the Markdown ("02134"); the quotes mark it as a deliberate string and are stripped from the value.

What if rows have different numbers of cells?

A row shorter than the header is padded with null for each missing column, so every record keeps the same shape. A row longer than the header is rejected with the row number, because the extra cells have no key and discarding them would corrupt the record quietly. Fix the row, not the schema.

Can I turn JSON back into a Markdown table?

Yes — the direction is fully served on this site. The JSON to Markdown table converter takes an array of records, unions their keys into a header, and emits a GFM table with pipe escaping applied where needed. Together the two pages make documentation round trips lossless for every shape a table can express.