Convert JSON to Markdown Tables & Lists
json to md with the shape of your data decided by the data itself: a top-level array of flat objects becomes a GitHub Flavored Markdown table, and anything nested becomes an indented bullet list with bolded keys. Parsing is the browser’s own JSON.parse, running in a Web Worker — no library download, no upload, no signup.Processing happens 100% in your browser — nothing is uploaded.
How to convert JSON to Markdown
- Provide the data: drop a .json file onto the dropzone, or paste the payload straight into the editor.
- Local processing: the browser's native JSON.parse runs in a Web Worker, the shape is inspected, and the data is rendered as a GFM table or a nested bullet list.
- Copy or download: copy the Markdown to your clipboard or save it as a .md file for a README, a wiki, or an Obsidian vault.
Why Convert JSON to Markdown with MD Convert?
Shape dispatch: tables for records, lists for hierarchy
An array whose every element is a flat object maps exactly onto a pipe table. As soon as one element holds a nested object or array, the whole structure renders as an indented bullet list instead — because a Markdown cell cannot contain a block, and stringifying the nesting would bury your data as unreadable [object Object] text.
Columns unioned across every row
Every key seen in any object becomes a column, in first-seen order, and an object missing that key emits an empty cell. Sampling only the first object — the common shortcut in json2md-style tools — silently drops optional fields that appear later in a real API payload.
Pipe escaping and explicit nulls
Any | inside a string value is escaped as \| so a URL, regex or log line cannot split a cell and desynchronise the row. An explicit null is rendered as inline code rather than as blank, keeping it distinguishable from a key that was simply absent from that object.
Zero dependencies, zero data leaving the device
There is no parser to download: JSON.parse is already compiled into your browser. An API response with customer records, a manifest holding an access token, or an unshipped schema is processed locally and never transmitted — verifiable in the DevTools Network panel.
JSON to Markdown: Before and After
A top-level array of flat objects is the one shape with an exact Markdown equivalent, so it becomes a pipe table. Keys are unioned across all rows, so a field missing from one object yields an empty cell rather than a shifted column.
[
{ "endpoint": "/v1/users", "method": "GET", "auth": true, "p95_ms": 42 },
{ "endpoint": "/v1/users", "method": "POST", "auth": true, "p95_ms": 118 },
{ "endpoint": "/v1/health", "method": "GET", "auth": false, "p95_ms": 3 }
]| endpoint | method | auth | p95_ms |
| --- | --- | --- | --- |
| /v1/users | GET | true | 42 |
| /v1/users | POST | true | 118 |
| /v1/health | GET | false | 3 |Understanding the JSON Format: RFC 8259 / ECMA-404
- Format
- JavaScript Object Notation
- Specification
- RFC 8259 / ECMA-404
- Media type
application/json- Parser used
- Native JSON.parse
JSON is defined twice, compatibly: RFC 8259 by the IETF and ECMA-404 by Ecma International. The grammar is deliberately tiny — objects, arrays, strings, numbers, and the three literals `true`, `false` and `null`. There is no date type, no comment syntax, no schema, and no notion of order beyond arrays being ordered and object members not being required to be.
That minimalism is why JSON is everywhere and also why converting it to Markdown is a structural problem rather than a parsing one. Parsing is free: the browser has a compliant, C-speed `JSON.parse` built in, so there is no third-party dependency and no WebAssembly module to download. The real question is what shape the data has, because Markdown offers exactly two containers — tables and lists — and JSON can nest arbitrarily deep.
The converter therefore dispatches on shape. A top-level array whose every element is a flat object maps exactly onto a GitHub Flavored Markdown pipe table, which is the single most common shape for an API response or a dataset dump. Anything else — a configuration object, a deeply nested schema, an array of mixed types — becomes an indented bullet list with the keys bolded, which is lossless with respect to hierarchy even though it is less compact.
When JSON becomes a table, and when it becomes a list
The table path has two conditions, and both must hold. The value at the top level must be a non-empty array, and every element must be a plain object whose own values are all scalars. If a single element contains a nested object or a nested array, the whole structure falls back to list rendering — because a Markdown cell cannot contain a table, and silently stringifying the nested value would hide data inside a cell as unreadable `[object Object]` text.
Column discovery is a union, not a sample of the first row. Every key seen in any object becomes a column, in first-seen order, and an object missing that key emits an empty cell. This matters for real API payloads, where optional fields are simply absent rather than present-and-null: taking the first object's keys as the schema — which is the common shortcut — silently drops every field that only appears later in the array.
The list path handles everything else and preserves hierarchy exactly. Each object key becomes a bullet with the key in bold, each nesting level adds two spaces of indentation, and array elements become bullets in order. Scalars are emitted inline next to their key, so a config file reads as a structured outline rather than as prose.
Escaping, null handling and type fidelity
The pipe character is structural in Markdown and meaningless in JSON, so every `|` inside a string value is escaped as `\|` before output. Without that, a single pipe in a URL, a regex or a log line would split one cell into two and desynchronise the entire row from its header — the most common way a generated table silently breaks.
`null` is rendered as inline code rather than as an empty cell, because the two are semantically different: an explicit `null` says the field exists and has no value, while an empty cell in a unioned table says the key was absent from that object. Keeping them visually distinct means the output can be read back without ambiguity.
Numbers and booleans are stringified exactly as JavaScript represents them, and strings are emitted as-is with no type coercion. Two consequences are worth knowing: JSON numbers are IEEE 754 doubles, so an integer beyond 2^53 in the source has already lost precision before conversion begins, and a quoted `"007"` stays `007` because it was a string in the source.
Nested schemas, config files and API responses
The three shapes people actually paste are an array of records, a single configuration object, and an envelope — an object with metadata at the top and the interesting array nested under a `data` or `items` key. The first becomes a table, the second becomes an outline, and the third becomes an outline whose nested array is rendered as a list of grouped bullets.
If what you want from an envelope is a table, extract the inner array so it sits at the top level, then convert. That is a deliberate design choice rather than a missing feature: guessing which nested array is the interesting one is exactly the kind of heuristic that works on the example and fails on the payload you care about.
For LLM and retrieval pipelines, the list rendering is usually the more useful of the two. Bolded keys next to their values give a chunk that reads as natural language and tokenises far more cheaply than pretty-printed JSON, where braces, quotes and indentation can account for a large share of the tokens without carrying meaning.
Parsing locally with the browser's own engine
There is no library involved on this page. Parsing is a call to the browser's native `JSON.parse`, which is a compiled, spec-compliant implementation already present in the runtime — nothing is downloaded and nothing is bundled for it. That is why conversion of a multi-megabyte payload feels instantaneous, and why work runs in a Web Worker so the interface stays responsive while it happens.
The privacy consequence follows directly: an API response holding customer records, a manifest containing an access token, or a schema you have not shipped yet is read from the file or textarea and processed on your own device. Nothing is transmitted, which you can verify in the Network panel of DevTools while converting.
When the input is not valid JSON, the parse error is surfaced with the position reported by the engine rather than being swallowed into a generic failure. A trailing comma, a single-quoted key, or an unescaped newline inside a string — the three most common causes — are all reported at the character where the grammar breaks.
Known limitations of JSON to Markdown conversion
Being explicit about what a converter cannot do saves you a wasted upload. These are the boundaries of what is recoverable from JSON programmatically:
- Only a top-level array of flat objects becomes a table. An array nested inside an envelope object renders as a list; extract it to the top level first if you want a table.
- An array whose objects contain nested objects or arrays falls back to list rendering entirely, because Markdown cells cannot contain block structures.
- Column alignment is not emitted for JSON tables — the delimiter row is plain `---`. Use the CSV converter if you need per-column alignment control.
- JSON has no date type, so timestamps are whatever the source encoded them as (an ISO string or an epoch number) and are passed through unchanged.
- Integers larger than 2^53 lose precision at parse time. That is a property of the JSON number type, not of the conversion.
- Key order follows the source document. There is no sorting or schema normalisation applied.
Who Converts JSON to Markdown?
Backend Developers
Dropping a real API response into a pull request, an incident write-up or endpoint documentation as a readable table instead of a 200-line pretty-printed blob.
Data Engineers
Turning a JSON Lines sample or a query result into a table for a data dictionary, without loading it into a notebook first.
Platform Engineers
Rendering a config or manifest into documentation that shows the nesting, so a runbook reader can see which key sits under which section.
Obsidian & Notion users
Importing exported app data — bookmarks, tracker history, API dumps — into a vault as native Markdown that stays searchable and diff-able.
How You Can Verify the Privacy Claim
Zero server upload
Conversion runs inside your browser tab. Open DevTools, switch to the Network panel, and convert a file: for every format except URL to Markdown you will see no request carrying your document — because there is no endpoint to send it to.
Off the main thread
Heavy parsing is dispatched to a Web Worker, so a 500-page PDF or a large spreadsheet never freezes the interface. Everything is plain JavaScript — no native plugin, no WebAssembly toolchain, nothing to install.
Nothing to sign up for
No login, no quota, no paywall, and no tracking tied to your files. Analytics are cookieless and aggregate only. Read the privacy policy for the full data-flow breakdown, including the one proxied exception.
The parsers doing the work
No proprietary black box: each format is handled by a widely audited open-source library, running client-side at the version pinned in our lockfile.
JSON to Markdown — FAQ
How do I convert JSON to a Markdown table?
Make the array of records the top level of the document. An array whose elements are all flat objects becomes a pipe table with column headers taken from the union of all keys. If your array is nested inside an envelope object under a key such as data or items, extract that inner array first — guessing which nested array is the interesting one is a heuristic that fails on real payloads.
What happens with deeply nested JSON or a config file?
It becomes an indented bullet list with each key in bold. Every nesting level adds two spaces of indentation and array elements stay in order, so the hierarchy of a schema or a configuration file is preserved exactly rather than flattened.
Are pipe characters and null values handled safely?
Yes. Pipes inside string values are escaped as \| so they cannot break the table structure, and null is emitted as inline code so it stays distinguishable from an empty cell caused by an absent key.
Is my JSON uploaded to a server?
No. Parsing uses the browser's built-in JSON.parse inside a Web Worker on your device. Nothing is transmitted, which you can confirm by watching the Network panel in DevTools while you convert.
Is the output usable in Obsidian, Hugo or an LLM pipeline?
Yes. The output is standard GitHub Flavored Markdown, so it renders in Obsidian, Notion, GitHub and any Jekyll or Hugo build. For retrieval and LLM chunking the list rendering is usually preferable: bolded keys beside their values tokenise far more cheaply than pretty-printed JSON, where braces and indentation consume tokens without carrying meaning.