JSON Graph Visualizer
See any JSON document as an interactive, collapsible node graph — pan, zoom and copy any path, entirely on this device.
Paste JSON, drop a file, or Load sample
Press ? for shortcuts
Do it offline:$ jq 'paths' response.json
How to use it
- Load the sample, paste a document into the left panel, or drop a .json file onto it. Below a quarter of a megabyte the graph redraws as you type; above that a render button shows the size — Render 512 KB — and holds until you click it or press ⌘/Ctrl + Enter.
- Drag the canvas to pan, and press + or − to zoom; 0 fits the whole graph back inside the frame. Only the canvas moves under you — the cards keep their computed positions, so nothing you are reading slides around as you navigate.
- Use a card's toggle to fold its branch: the node stays in place carrying a count of what it hides, and the subtree beneath it leaves the picture until you open it again. The Flow control swings the whole layout between left-to-right and top-to-bottom.
- Click a card's title to light its address in the breadcrumb, then Copy path in JSONPath, jq, dot or bracket form, or Copy value for the raw source text. Download SVG saves the current picture as a vector file; Share folds the document and your open branches into a link.
Paste a JSON document and watch it become a graph of connected cards: every object and array turns into a node, its scalar fields sit inside as rows, and each nested container fans out along an edge you can trace with your eye. Pan and zoom the whole map, fold the branches you do not need, and copy the path or value of any node — all computed on this device, with nothing uploaded.
How it works
RFC 8259 gives JSON exactly six value shapes, and this view splits them into two jobs. The two containers — object and array — become cards, since they are the only shapes that can hold other values. The four scalars — string, number, boolean and null — cannot branch, so they sit inside their parent card as labelled rows. Flat text hides that split a few braces deep; drawing containers as boxes and their links as edges puts the branching back where the eye can follow it.
One walk over the parsed document builds the picture: each object or array emits a card, each scalar field a row on its parent, and each nested container one edge, from the row that names it to the card it opens. A field holding a thousand numbers stays one card, never a thousand boxes. Past five thousand objects and arrays the arrangement becomes an unreadable tangle, so the view stops, reports the count, and hands off to the JSON Tree Viewer, which pages any size as an outline.
Card positions come from arithmetic, not a physics simulation. Depth fixes the column — the root at one edge, its children a step along — while a single tidy-tree pass stacks siblings and centres each parent over the block of its descendants, every coordinate a whole number. Nothing reads a clock or a random seed, so one document and collapse state resolve to the same coordinates on any machine. So a shared link reopens to the arrangement the sender saw, and a screenshot lines up pixel for pixel.
A row shows a slice of your original text, not a value parsed and printed back. A number row keeps the digits that were in the file, so an identifier past 2^53 — where the JavaScript number type stops holding every integer — keeps its last digit, and Copy value returns those same characters. Folding a branch is pure subtraction: the collapsed card keeps a badge with its child count while its whole subtree leaves the nodes, edges and layout. Copy path spells an address as JSONPath (standardized in RFC 9535), a runnable jq filter, or JavaScript dot or bracket notation — whichever the next tool wants.
Examples
{
"service": "checkout",
"orders": [
{ "id": 9007199254740993, "status": "paid" },
{ "id": 9007199254740994, "status": "refunded" }
],
"flags": { "beta": true, "trace": false }
}Graph — 5 nodes, 4 edges, depth 3Five containers become five cards — the root object, the orders array, its two order objects, and the flags object — joined by four parent-child edges. The scalar fields (service, each id and status, beta, trace) are rows on their cards, not nodes.
{"eventId":9007199254740993}9007199254740993The eventId row shows this value and Copy value returns it exactly, because both read the source characters. JSON.parse hands back 9007199254740992 instead — one short, and silently — because the id has crossed 2^53. The graph never runs it through that conversion.
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119]+20 more fieldsAn array of 120 numbers is one card, not 120. The first 100 draw as rows and the rest fold into a single +20 more fields row, so a wide leaf never stretches a card off-screen. The engine also warns the node was summarized; the hidden count is exact.
{
"region": "eu-west-1",
"services": {
"api": { "port": 8080, "replicas": 3 },
"worker": { "port": 9090, "replicas": 2 }
},
"meta": { "owner": "platform" }
}Graph — 3 nodes, 2 edges, depth 2The same document with the services branch folded: its api and worker cards leave the graph, services keeps a 2 hidden badge, and the digest drops from five cards to three. Because the layout is deterministic, a link carrying this collapse reopens to the same three-card picture.
Every example on this page is executed against the same engine that powers the tool, on every build.
Gotchas worth knowing
Too many objects and arrays to draw
The graph draws up to five thousand cards; past that a diagram becomes an unreadable tangle, so the view declines rather than place boxes you could not use, and it names the real count it counted. A document that dense is a job for the JSON Tree Viewer, which reads the same structure as a foldable outline.
A list of thousands of scalars stays one card
A leaf array or object of hundreds of primitive values does not explode into hundreds of nodes. It is one card whose first hundred values are rows and whose remainder is a +N more summary, with N the honest count left off.
A list of thousands of objects is refused, not thinned
The row summary applies to values, never to structure: every nested object and array is a card that anchors edges, so those are always drawn in full. An array of many thousands of objects therefore hits the card ceiling and triggers the total refusal above, not a partial graph that would misstate the document's shape.
Big identifiers keep every digit
A whole number over 2^53 is past the range where the JavaScript number type holds every integer. Because a row is a window onto the source text and not a parsed float, the graph shows and copies such an id untouched. The eventId in the examples above is the proof: the console rounds it, this view does not.
The same document always draws the same picture
Card positions come from integer arithmetic with no clock and no random seed, so a document and its folded branches resolve to one fixed picture everywhere. That is what lets a shared link, a downloaded SVG and a teammate's screen agree, and why the layout is safe to screenshot.
Repeated keys are shown twice, with a badge
When one object carries the same key twice, both entries stay as rows on the card, each wearing a badge, and the parser's own note names the key with its two line numbers. The graph refuses to pick a winner, because which duplicate survives is decided by whatever reads the data next, not by this page.
Data URIs get a chip, not a render
A string that begins with data: is tagged with a chip stating its byte size instead of unrolling a base64 blob across the card. The payload is neither decoded nor drawn; Copy value still returns the whole URI, so the tool you paste it into next receives every byte.
Common errors
Unexpected ']' at line 1, column 18 — probable cause: trailing comma after the last element.- The caret sits on the bracket the stray comma orphaned, not on the comma — that is where the grammar breaks, a habit JSON5 and JSONC allow but JSON does not. While the text is invalid the previous graph stays on the canvas, dimmed and stale, so your zoom and folded branches survive the typo; it rebuilds once the document parses again.
This document has 5,001 objects and arrays — more than the 5,000 this graph view can render.- Five thousand cards is where the layout stops being a diagram and becomes noise, so the view declines rather than draw a canvas you could not navigate. The number it prints is the real container count it found. For structure this large the JSON Tree Viewer is the better lens, and the message links you straight to it.
Input is larger than the 4 MB limit for this graph view.- The ceiling is about layout, not parsing: positioning that many cards would freeze the tab long before the picture could help. Nothing you pasted is changed or dropped. The jq command in the banner lists every path in a file of any size, runs on your machine, and keeps the data as private as this page.
FAQ
When is the graph a better choice than the JSON Tree Viewer?
Use the graph when the connections between branches matter more than raw contents. The Tree Viewer is a vertical outline built to search and page through very large files in place; this graph spreads the structure across a canvas so you see how those branches join at a glance. Reach for the graph to grasp shape, and the viewer when the document is huge or you need a key by name.
What happens when a document is too big to graph?
Two ceilings apply: past four megabytes of text, or past five thousand objects and arrays, the view refuses outright instead of drawing a frozen or partial picture, and it tells you which limit you met. Both messages point at the JSON Tree Viewer and a jq command that lists paths for a file of any size, so there is always a next step.
Can I rearrange the graph by dragging nodes around?
No — positions are computed, and dragging cards into a hand-drawn diagram is deliberately out of scope. Pan and zoom move your view of a fixed layout, which is what keeps every render, link and screenshot of the same document identical. Free-form diagram editing is a drawing tool's job, not a reader's.
Does my JSON get uploaded when I render it?
No. Parsing, layout and every path or value you copy run inside your browser tab, and a dropped file is read straight from disk with no request leaving the page. Nothing persists between visits unless you Share, and a Share link keeps its state in the URL's # fragment — the part a browser never transmits to any server.
Can I send someone a link to one branch of the graph?
Yes. Share encodes the document, your folded branches and the selected node into the link's # fragment, and because the layout is deterministic it reopens to the same arrangement with the same node lit. Two honest limits: a very large state offers a file download instead of a link, and credential-shaped input asks for confirmation first.
Which of the four Copy path formats do I want?
Pick the one your next step reads. JSONPath, the form that opens with a dollar sign, is what API assertion suites and document databases speak. The jq form is the same address as a filter you can run unedited. Dot notation drops into most languages; bracket notation is its safe twin for keys holding a space, dot or dash. Every button addresses the node you have selected.
Keyboard shortcuts
- ⌘/Ctrl + Enter
- Render the graph now at any size — the large-input band's run key; works with the cursor still in the input panel.
- ⌘/Ctrl + S
- Download the current graph as an .svg vector file; on this page it overrides the browser's own save dialog, as the help overlay warns.
- ⌘/Ctrl + C
- With a node selected, copies that node's value exactly as written in the source — the whole document when no node is selected. A real text selection copies itself, untouched.
- ⌘/Ctrl + Shift + C
- Copy the entire document, whatever is selected or focused.
- + / − / 0
- Zoom in, zoom out, or fit the whole graph back to view; these move the canvas only and never disturb the computed layout.
- t
- Cycle the color theme (single keys stay inert while typing in a field, during IME composition, and when disabled in settings).
- ? or ⌘/Ctrl + /
- Open keyboard help — the render, copy, zoom and theme keys, plus the ⌘S conflict note.
- Esc
- Close the topmost dialog; it never touches the input or the graph.