JSON Tree Viewer
Paste any JSON and explore it as a collapsible, color-coded tree, click any key to expand or collapse its children.
About the JSON Tree Viewer
Drop in a JSON document and it turns into an interactive, collapsible tree on the spot, with objects and arrays showing their key or item count when folded up and each value color-coded by type. Because the tree is built from real DOM nodes instead of an HTML string, there's no risk of whatever you paste in being interpreted as markup.
Why building the tree from real DOM elements matters for safety
Every piece of text in this viewer, keys, string values, everything, is placed onto the page with textContent on elements created via document.createElement, never by assembling an HTML string and injecting it with innerHTML. That distinction is what makes this viewer genuinely safe to paste arbitrary, untrusted JSON into: even if a string value in your JSON literally contained something like <script>alert(1)</script>, textContent renders it as inert, visible text exactly as written, the browser never interprets it as markup to execute. A tree viewer built by concatenating an HTML string instead would risk exactly that kind of unintended code execution from data that's supposed to be inert.
Why string values get re-run through JSON.stringify for display
Rather than displaying a string value's raw characters directly, the viewer wraps it with JSON.stringify(value) before showing it. This does two things at once: it adds back the surrounding quote marks so it visually reads as a JSON string, and it correctly re-escapes any special characters the string contains, embedded quotes, newlines, tabs, back into their proper escaped form. That guarantees what's displayed always matches valid JSON string syntax exactly, rather than showing a raw, unescaped dump that could look ambiguous or, for a string containing an actual newline character, visually break across lines in a confusing way.
How arrays and objects share one rendering path
Rather than writing separate rendering logic for arrays and objects, the tree builder first converts both into the same shape, a list of [key, value] pairs, using Object.entries() for objects and a manual .map((v, i) => [i, v]) for arrays that pairs each item with its numeric index. Once both container types are normalized into that identical pair-list format, the exact same recursive function builds child nodes for either one without needing to branch into array-specific and object-specific code paths, the only real difference that survives is which bracket characters and whether the count is labeled "items" or "keys."
Why Expand All and Collapse All don't rebuild the tree
Every node's children and its collapsed-state summary text stay in the DOM at all times, whether expanded or collapsed, only their visibility toggles via a CSS class and inline display changes. That's why clicking Expand All or Collapse All is fast even on a fairly large tree, it's just a bulk querySelectorAll sweep flipping visibility classes and arrow characters, not a full re-parse and re-render of your JSON from scratch.
A performance consideration for very large JSON documents
Because every node in the tree is a genuine DOM element rather than a lightweight virtual representation, an extremely large or deeply nested JSON document, thousands of keys, deeply recursive structures, can produce thousands of real DOM nodes all at once, which may render noticeably slower than a document with a few dozen keys. For typical API responses, config files, and everyday debugging, this is imperceptible, but if you're inspecting a genuinely enormous JSON dump, expect the initial render (and Expand All specifically) to take a moment longer than it would on smaller data. Starting with everything collapsed and expanding only the branches you actually need to inspect is a reasonable workaround for particularly large payloads.
Frequently Asked Questions
Is it safe to paste JSON that might contain HTML or script-like text?
Yes, every piece of text is rendered using textContent on real DOM elements, never innerHTML. Even a string value containing something like a script tag is displayed as inert, visible text, the browser never interprets pasted data as executable markup.
Why are string values shown with quotes and escaped characters rather than raw?
Each string value is passed through JSON.stringify() before display, which adds back the surrounding quotes and correctly re-escapes special characters like embedded quotes or newlines. This ensures the displayed text always matches valid JSON string syntax rather than showing a potentially confusing raw dump.
Does the viewer use different logic for rendering arrays versus objects?
No, both are first converted into the same list of [key, value] pairs (using array indexes as keys for arrays), then one shared recursive function builds the tree nodes for either type, avoiding separate array-specific and object-specific rendering code.
Does clicking Expand All re-parse my JSON from scratch?
No, every node's children already exist in the DOM regardless of collapsed state, Expand All and Collapse All just toggle visibility classes and arrow icons across all nodes at once. This is much faster than rebuilding the tree.
Will a very large JSON document render slowly?
Possibly, since every node is a genuine DOM element rather than a lightweight virtual one, a document with thousands of keys can produce thousands of real DOM elements. Typical API responses and config files render instantly, but extremely large JSON dumps may take noticeably longer to render.
Does the tree viewer send my JSON anywhere?
No, parsing and rendering both happen entirely in your browser using JSON.parse and DOM APIs. Nothing you paste is uploaded to a server.