How to convert json test fixtures to a markdown table
- Step 1Pick representative fixtures — Choose fixtures that exercise the full shape — including ones with optional or edge fields populated — so the union of keys documents every column a new developer should know about.
- Step 2Anonymize realistic data — If fixtures contain realistic emails, names, or secrets, anonymize them or run md-secret-redactor before pasting. The tool converts exactly what it's given.
- Step 3Flatten nested fixture shapes — Nested objects render as
[object Object]. Promote the sub-fields you want to teach (e.g.payload.userId→payload.userId) to top-level keys before converting. - Step 4Paste and Run — Paste the fixture array (or upload the
.json). No options to set — Run builds the table with columns from every fixture's keys. - Step 5Check the column set covers the shape — Confirm the headers match the data shape you want new developers to learn. Missing a column means no sample fixture used that field — add one that does.
- Step 6Embed in onboarding docs — Paste the table into the onboarding guide or test-setup README. To publish, convert with md-to-html; for a handbook deliverable, md-to-docx.
Fixture value types in the output
How fixture values render in the table. Every cell is String(value ?? "").
| Fixture field | Example value | Cell output |
|---|---|---|
| Id (string) | "fx_01" | fx_01 |
| Count (number) | 0 | 0 |
| Flag (boolean) | true | true |
| Date string | "2026-06-13" | 2026-06-13 |
| Null field | null | (empty cell) |
| Field absent in this fixture | (missing) | (empty cell) |
| Nested payload object | {"k":1} | [object Object] — flatten first |
| Tags array | ["a","b"] | a,b |
Union-of-keys behavior for fixtures
Why a heterogeneous fixture set still documents every field. Columns appear in first-seen order.
| Fixture set | Columns produced | Empty cells where |
|---|---|---|
| All fixtures identical | Exactly those keys | Where values are null/missing |
| One fixture adds an edge field | All keys, union | Other fixtures' rows, that column |
| Happy-path + error fixtures differ | Every key from both | Each row lacks the other's fields |
| A fixture is a primitive | Keys from object fixtures only | The primitive fixture's whole row |
Tier limits
Markdown-family caps. Fixture samples are small; uploads matter only if you dump a whole fixtures file.
| Tier | Upload size | Paste characters | Files/run |
|---|---|---|---|
| Free | 1 MB | 500,000 | 1 |
| Pro | 10 MB | 5,000,000 | 10 |
| Pro-media | 50 MB | 20,000,000 | 50 |
| Developer | 500 MB | unlimited | unlimited |
Cookbook
Fixture patterns from real test suites and the tables they produce. Fixture data is anonymized.
A straightforward fixture array
The common case: uniform fixtures with primitive fields. New developers immediately see the expected shape.
Input:
[
{"id": "fx_1", "role": "admin", "active": true},
{"id": "fx_2", "role": "viewer", "active": false}
]
Output:
| id | role | active |
| --- | --- | --- |
| fx_1 | admin | true |
| fx_2 | viewer | false |Happy-path and error fixtures together
Error fixtures often carry extra fields (an error code, a reason). The union rule documents both shapes in one table; happy-path rows leave the error columns blank.
Input:
[
{"case": "ok", "status": 200},
{"case": "not_found", "status": 404, "error": "NO_USER"}
]
Output:
| case | status | error |
| --- | --- | --- |
| ok | 200 | |
| not_found | 404 | NO_USER |Zero and false are shown, not blanked
A subtle teaching point: 0 and false are real values and render as text — only null and missing fields are blank. This helps new developers distinguish 'set to zero' from 'unset'.
Input:
[
{"id": 1, "retries": 0, "verbose": false},
{"id": 2, "retries": null}
]
Output:
| id | retries | verbose |
| --- | --- | --- |
| 1 | 0 | false |
| 2 | | |Flatten a nested payload fixture
A nested payload becomes [object Object]. Promote its fields so the onboarding table teaches the real inner shape.
Raw fixture:
{"event": "signup", "payload": {"plan": "pro", "trial": true}}
Flatten to:
[{"event": "signup", "payload.plan": "pro", "payload.trial": true}]
Output:
| event | payload.plan | payload.trial |
| --- | --- | --- |
| signup | pro | true |A fixture value with a pipe is preserved
Fixtures that test parsing often include pipes. The tool escapes | so the table stays aligned.
Input:
[{"case": "alt", "input": "a|b|c"}]
Output:
| case | input |
| --- | --- |
| alt | a\|b\|c |Edge cases and what actually happens
Nested fixture payloads show as [object Object]
By designA fixture field that's itself an object renders as [object Object] because the tool uses String(). Flatten the inner shape into top-level keys to teach it, or give the payload its own table in the onboarding doc.
Array fixtures collapse to comma text
By designA tags: ["a","b"] fixture field becomes a,b. An array of nested objects becomes [object Object],[object Object]. Document collection fixtures with a dedicated table rather than inline.
Realistic PII left in fixtures
Privacy riskThe tool converts verbatim. Fixtures with realistic emails, names, or secrets will appear in the published onboarding doc. Use anonymized fixtures, or run md-secret-redactor for tokens, before converting.
Fixtures file is JSONL (one per line)
Invalid JSON inputSome suites store fixtures as newline-delimited JSON, which isn't a single valid document — the tool returns Invalid JSON input.. Wrap the lines into a JSON array ([obj, obj]) first.
Empty fixture array
Empty arrayAn input of [] returns Empty array.. Provide at least one fixture object.
Fixtures are bare values, not objects
No object keys foundAn array of primitives (["a", "b"]) returns No object keys found. because there are no keys. Wrap each in an object — [{"value":"a"}] — for a one-column table.
A fixture string contains a newline
Row breakA multi-line fixture value (a formatted body or template) breaks the row because newlines aren't escaped. Replace newlines with spaces in the sample, or re-align with md-table-repair.
Snapshot/JSON Schema instead of fixtures
Wrong shapeA JSON Schema document or a Jest snapshot is one nested object, not an array of records — it produces a single [object Object]-heavy row. Document schemas separately; this tool is for arrays of example fixture records.
Inconsistent field names across fixtures
Two columnsuserId in one fixture and user_id in another become two columns under the union rule. Normalize fixture key names so the onboarding table shows a single column per field.
Fixtures file exceeds the paste limit
413 over limitA full fixtures file can exceed the paste character cap (Free 500,000). Upload the .json (Free 1 MB), trim to a representative sample, or upgrade for higher limits — onboarding tables rarely need every fixture.
Frequently asked questions
How are columns chosen when fixtures differ?
Columns are the union of every key across every fixture, in first-seen order. So an error fixture's extra fields and a happy-path fixture's fields all appear; rows that don't include a field show an empty cell. This documents the full shape in one table.
Will 0 and false show up, or be blanked?
They show as 0 and false. Only null and missing keys render as empty cells. This is a useful onboarding distinction: a blank cell means unset, while 0/false are real values the fixture sets deliberately.
How are nested fixture objects handled?
They render as [object Object], because each cell is produced with String() rather than JSON.stringify. Flatten the inner fields you want to teach (e.g. payload.plan) into top-level keys before converting, or give the nested payload its own table.
Can I convert a JSON Schema or a snapshot?
Not usefully — those are single nested objects, not arrays of records, so you'd get one row full of [object Object] cells. This tool is for arrays of example fixtures. Document schemas and snapshots separately.
Should I anonymize fixtures first?
Yes if they contain realistic PII or secrets — the tool converts verbatim and redacts nothing. Use anonymized fixtures, or run md-secret-redactor to strip tokens, before converting for a published onboarding doc.
My fixtures are stored as JSONL — can I convert them?
Not directly. Newline-delimited JSON isn't a single valid document, so you'll get Invalid JSON input.. Wrap the lines into a JSON array first, then convert.
Are there any options to configure?
No — none. Paste the fixture array (or upload one .json) and Run. The column set, separators, and escaping are automatic. The sibling csv-to-md-table has a header-row option if your fixtures are CSV instead.
Are my fixtures uploaded anywhere?
No. Conversion runs entirely in your browser tab — proprietary fixtures never reach a server. The only server write is an anonymous usage counter for signed-in dashboards, with no content.
What about pipes and newlines in fixture values?
Pipes are escaped to \| so they don't break columns — handy for fixtures that test parsing. Newlines are not escaped, so a multi-line fixture value will break the row; replace newlines with spaces first.
Why did I get 'No object keys found.'?
Your fixture array holds primitives, not objects (e.g. ["a", "b"]). Wrap each value in an object — [{"value": "a"}] — to produce a one-column table.
How big a fixtures file can I convert?
Free allows a 1 MB upload or 500,000 pasted characters; Pro 10 MB / 5,000,000; Pro-media 50 MB / 20,000,000; Developer 500 MB / unlimited. For onboarding you'll usually trim to a small representative set.
How do I publish the fixtures table?
Send the Markdown to md-to-html for a web page, or md-to-docx for a handbook. If a table gets misaligned during edits, md-table-repair re-aligns it. Both are markdown-family siblings.
Privacy first
All Markdown processing runs locally in your browser using JavaScript. No file is ever uploaded to JAD Apps servers — only metadata counters are saved for signed-in dashboard stats.