Format, minify, sort, repair and query JSON with JSONPath, without rounding a big number or dropping a duplicate key. The document stays in the browser.
How it works
Most formatters run the text through JSON.parse and JSON.stringify. That is how 12345678901234567890 becomes 12345678901234567000, 1.0 becomes 1, a second "tag" key replaces the first, and keys that look like integers jump to the front. This page reads the document into a syntax tree instead and prints every number, string and key back as it was written, so Format, Minify and Sort Keys change the layout and nothing else.
Edit mode has the toolbar: Format at 2, 4 or 8 spaces, Sort Keys, Minify, Escape, Unescape, a Transform menu with Repair, Expand embedded JSON and the JSON Lines conversions, and a Fold menu. Each action answers in the bar under the editor, and one that cannot run says why and where. The bar also shows the JSONPath of the caret, and a count of keys or elements sits beside every brace.
Query mode puts a JSONPath box above the document and the matches beside it, as values or as normalised paths. The language is RFC 9535, filters and its five functions included, and it runs over the same tree, so a name selector returns every entry under a duplicated key.
For JSON Lines, one value per line, Array to JSON Lines writes each element minified on its own line and JSON Lines to array reads them back. Minify and Sort Keys work line by line; Format refuses, since a value spread over several lines is no longer JSON Lines.
Examples
A long ID and a repeated key
{"id": 12345678901234567890, "price": 1.0, "tag": "a", "tag": "b"}
Format at 2 spaces keeps all four entries as written:
{
"id": 12345678901234567890,
"price": 1.0,
"tag": "a",
"tag": "b"
}
JSON.stringify(JSON.parse(text), null, 2) rounds the ID, drops the decimal point and loses the first tag:
{
"id": 12345678901234567000,
"price": 1,
"tag": "b"
}
Repairing a hand-written object
{
// exported from a config
name: 'Ada',
tags: ['maths', 'engines',],
active: True,
ratio: NaN,
}
{
"name": "Ada",
"tags": [
"maths",
"engines"
],
"active": true,
"ratio": null
}
The status bar lists what changed: 1 comment removed, 2 trailing commas removed, 3 single-quoted strings requoted, 4 bare keys quoted, 1 Python or JavaScript literal replaced, 1 non-finite number made null.
Filtering with JSONPath
{
"store": {
"book": [
{ "title": "Sayings of the Century", "price": 8.95 },
{ "title": "Sword of Honour", "price": 12.99 },
{ "title": "Moby Dick", "price": 8.99 }
]
}
}
$.store.book[?@.price < 10].title finds 2 matches. With Result set to Paths:
[
"$['store']['book'][0]['title']",
"$['store']['book'][2]['title']"
]
Common problems
Trailing commas and comments
JSON allows neither, so {"a": 1,} stops Format with “Not valid JSON at line 1, column 9”, the brace the comma was waiting for. JSONC, which VS Code's settings.json is written in, and JSON5 allow both; Repair removes them.
Single quotes, bare keys and Python's True
A JavaScript object literal or a Python repr looks like JSON and is not. Repair requotes the strings, quotes bare keys, reads 0xFF as 255, and turns True, None and undefined into true and null. NaN and Infinity have no JSON spelling and become null, which changes the value and is listed separately. A Python tuple stops the repair at its bracket.
Integers above 2^53
A JavaScript number is a double, so JSON.parse("9007199254740993") gives 9007199254740992. RFC 8259 only promises that integers within ±(2^53-1) are read alike everywhere. This page keeps every digit, but whatever reads the result next may still round it; an ID sent as a string is safe.
A duplicate key only some tools see
RFC 8259 says names SHOULD be unique and leaves a repeat to the parser, and JSON.parse silently keeps the last. Here both stay visible, Sort Keys puts them side by side in their written order, and a query for the name returns both.
Frequently asked questions
Does Repair guess at missing brackets?
No. A truncated document or an unclosed string is reported with its place: {"a": [1, 2 gives “Could not repair: the document ends before its "]" at line 1, column 12”. Closing brackets until something parses would produce a document nobody wrote.
How does Sort Keys order the keys?
By character code, at every depth, so digits come before capitals and capitals before lower case: "Zeta" sorts ahead of "alpha". Arrays keep their order, and two entries with the same name stay in the order they were written.
What is Expand embedded JSON for?
A log line or webhook often carries an object stored as a string. Expand opens every string that holds an object or an array, however deep, and leaves "42" and "true" alone, since unquoting those would change their type. Escape and Unescape go the other way, turning the whole document into one string and back.
Can it check the document against a schema?
No; the editor only checks that it is JSON. The schema validator takes a JSON Schema, Zod or Pydantic model and marks each fault in the payload.