Validating JSON means checking that it can be read and that it arrives unchanged
JSON follows the syntax defined by RFC 8259 and ECMA-404. Objects go in curly braces { }, arrays in square brackets [ ], keys and strings in double quotes, and a value can only be a string, number, true, false, null, object or array. If a single character breaks these rules, the receiving program cannot read the whole document. JavaScript's JSON.parse throws a SyntaxError for one trailing comma or one single quote.
This validator reads what you paste with the strict standard syntax. If the syntax is wrong, it shows the line and column where parsing stopped, the lines around it, and the place where an unclosed bracket was opened. Notations that are common in hand-edited configs or text copied from other languages (comments, trailing commas, single quotes, unquoted keys, True and so on) are collected so they can be fixed automatically. If the syntax is valid, you get a collapsible tree, and selecting a value shows its path and how much space it takes up.
Valid syntax can still change in the receiving program. When the same key appears twice, most programs lose the earlier value, and a big integer such as 9007199254740993 is read by JavaScript as 9007199254740992. These cases are kept apart from errors and listed under Warnings below.
When to validate and expand JSON
- Checking an API response: when a response arrives as one long line, it is hard to see which value sits where. Paste it to get a tree, then click a value to copy a path such as
$.items[2].price. - After editing a config file: with files you edit by hand, such as package.json, tsconfig.json or VS Code settings, one missing comma stops the program from starting. Paste the file before saving and you get the line number right away. For a file that allows comments, like tsconfig.json, auto-fix can make a copy with the comments removed before you pass it to another tool.
- JSON copied from logs or chat: text that went through a messenger or word processor may have curly quotes, stray special spaces from a web page, or Python-style single quotes and True. These characters look the same to the eye, so the tool points them out with their position.
- Finding why a response is heavy: the weight map draws each value under the chosen object or array with an area proportional to its bytes. A field holding a base64 thumbnail or an array that repeats the same content stands out at a glance.
- Before sending to another system: big integers such as order numbers or tweet IDs, duplicate keys in one object, and unpaired emoji escapes pass a syntax check but change on the receiving side. Check the Warnings list first.
How to use it
- Paste JSON into the source box, or open a .json file with Open file or by dropping it in. The check runs as soon as you stop typing, and Ctrl+Enter (⌘+Enter on a Mac) runs it again immediately.
- If there are errors, the error diagnosis and auto-fix appear below. Click 'Go to error' in the status line to put the cursor on that character in the source box. If only automatically fixable notations are left, 'Apply N fixes to the source' fixes them at once, and Undo in the status line brings the original back.
- If the syntax is valid, choose a value in the tree on the left. Use the triangle or a double-click to expand and collapse branches, or move with the arrow keys. Moving the cursor in the source box makes the tree follow to that value.
- In the inspector on the right, pick a path format (JSONPath, JavaScript, Python, jq or JSON Pointer) and click Copy path. Copy value copies only the chosen value as JSON with 2-space indentation (for a string, the text without quotes).
- Use the buttons under the source box to reformat with 2 or 4 spaces or compact to one line, then copy or save as a .json file. Reformatting keeps numbers exactly as written and does not remove duplicate keys.
Error messages and how to fix them
Paste an input from the table into this validator and you get the message in the middle column. The position points at the character where parsing stopped. The one exception is a missing comma: it points at the place where the comma belongs, right after the previous value. Forgetting a comma at the end of a line is the most common slip, and showing the end of the previous line is easier to follow than the first character of the next one.
| Example input | Message from this validator | How to fix it |
|---|---|---|
[1, 2, 3,] | There is a comma after the last item | Delete the comma before the closing bracket |
{"a": 1 "b": 2} | A comma is missing between items | Put a comma right after the 1 |
{'a': 1} | Strings must be wrapped in double quotes | Change 'a' to "a" |
{a: 1} | This key has no double quotes: a | Wrap the key as "a" |
{"a": 1, /* note */ "b": 2} | JSON does not allow comments | Delete the comment |
{"ok": True} | This is Python notation, not a JSON value: True | Write lowercase true |
{"avg": NaN} | JSON has no such value: NaN | Change it to null or a string |
{"zip": 04001} | A number cannot have a leading zero: 04001 | Write it as a string, like "04001" |
["first line↵second line"] | The line breaks inside a string | Write the line break as \n |
{"path": "C:\Users\emma"} | This escape does not exist in JSON: \U | Write the backslash twice, as \\ |
{"data": [1, 2 | The document ended while a bracket is still open | Check whether it was cut off; if it really ends there, add ]} |
{"a": 1}↵{"a": 2} | There is more text after the JSON value ended | Wrap the objects in an array or treat the text as JSONL |
{“a”: 1} | This is a curly quote, not a straight one: “ | Replace it with a straight double quote " |
If the document ends while brackets are open, the diagnosis lists the closing characters needed at the end, innermost first. For {"data": [1, 2 that is ]}. But if the response was cut off while you copied it from a log or screen, the data after the cut is missing, so it is better to fetch the original response again than to add brackets just to make the syntax pass.
What auto-fix changes and what it leaves alone
Auto-fix turns notations that come from extended formats such as JSON5 and JSONC, from Python and JavaScript code, or from word processors into standard JSON. It keeps the line layout and indentation, changes only the characters involved, and removes a line entirely if it held nothing but a comment. The 'Apply N fixes to the source' button appears only when the fixed result passes the strict check again. If other errors would remain after fixing, you get a note to fix those first instead of the button.
| Notation fixed | Input | Auto-fix result |
|---|---|---|
| Comments | {"a": 1 /* memo */} | {"a": 1 } |
| Trailing commas | [1, 2, 3,] | [1, 2, 3] |
| Missing commas | {"a": 1 "b": 2} | {"a": 1, "b": 2} |
| Single-quoted strings | {'name': 'it\'s'} | {"name": "it's"} |
| Curly quotes | {“name”: “Emma”} | {"name": "Emma"} |
| Unquoted keys | {name: "Emma", 2024: true} | {"name": "Emma", "2024": true} |
| Python and uppercase values | [True, False, None, NULL] | [true, false, null, null] |
| NaN, Infinity, undefined | [NaN, Infinity, -Infinity, undefined] | [null, null, null, null] |
| +1, .5, 5., 0x1F numbers | [+1, .5, 5., 0x1F] | [1, 0.5, 5.0, 31] |
| Line breaks and tabs in strings | ["first line↵second line", "a→b"] | ["first line\nsecond line", "a\tb"] |
| Special space (NBSP) | {"a":⍽1} | {"a": 1} |
| Leading BOM | [BOM]{"a": 1} | {"a": 1} |
Changing NaN, Infinity and undefined to null changes the meaning. JSON numbers have no infinity or NaN, so null is the only slot the standard offers, but if the receiving program has to tell 'no value' from 'NaN', a string is the better choice. A hexadecimal number is converted to decimal only when it does not exceed 2⁵³−1.
The following are left alone on purpose. For a number with leading zeros (04001), the tool cannot know whether it should be text, like a ZIP code, or a number. For the doubled commas in [1,,2], it cannot know whether an empty value was intended, and a truncated document cannot be restored. JSONL, with one object per line, is a different format rather than something to fix, so use a JSON array to JSONL converter. Array items missing a comma on the same line ([1 -2], ["a" "b"]) are also left alone: in Python or JavaScript these subtract or join the strings, so adding a comma would change the meaning. Commas are inserted only at line breaks and before object keys.
Five path notations
When you select a value in the tree, the path to it is written in five notations. The same value is written differently depending on where you use it. JSONPath is used in Postman, many API testing tools and database queries. JavaScript and Python notation go into code, jq on the command line, and JSON Pointer in JSON Patch (RFC 6902) or the $ref of JSON Schema. In the JavaScript and Python notation, data stands for the variable that holds the parsed JSON.
| JSONPath | JavaScript | Python | jq | JSON Pointer |
|---|---|---|---|---|
$.items[2].options.gift_wrap | data.items[2].options.gift_wrap | data["items"][2]["options"]["gift_wrap"] | .items[2].options.gift_wrap | /items/2/options/gift_wrap |
$.headers['x-request-id'] | data.headers["x-request-id"] | data["headers"]["x-request-id"] | .headers["x-request-id"] | /headers/x-request-id |
$.café.menü | data.café.menü | data["café"]["menü"] | .["café"]["menü"] | /café/menü |
$['a/b']['m~n'] | data["a/b"]["m~n"] | data["a/b"]["m~n"] | .["a/b"]["m~n"] | /a~1b/m~0n |
$ | data | data | . | empty string |
Each notation allows a different range of keys after a dot (.). The JSONPath standard (RFC 9535) allows letters, underscores and any character from U+0080 up in dot notation, so a key with an accent such as café is written $.café.menü. jq allows only letters, digits and underscores after a dot, so a key with an accent or a hyphen is wrapped in brackets like .["café"]. JavaScript follows its identifier rules, so a key with an accent works with a dot, while a key with a hyphen such as x-request-id needs brackets. JSON Pointer joins keys with /, so a ~ inside a key becomes ~0 and a / becomes ~1, and the whole document is the empty string.
When valid syntax still changes the value
Big numbers. JSON syntax sets no limit on the number of digits, but RFC 8259 notes that most programs handle numbers as IEEE 754 binary64 (double-precision floating point), and that integers are read the same everywhere only from −(2⁵³−1) to 2⁵³−1. A larger integer, or a decimal with too many significant digits, becomes the nearest binary64 value. This validator compares the significant digits you wrote with the value that is read, and flags only the numbers that change.
| Number written in JSON | Value JavaScript reads | This validator |
|---|---|---|
9007199254740991 | 9007199254740991 | Unchanged (largest safe integer) |
9007199254740993 | 9007199254740992 | Precision loss |
1234567890123456789 | 1234567890123456800 | Precision loss |
0.1234567890123456789 | 0.12345678901234568 | Precision loss |
1.10 | 1.1 | Unchanged (same value; the digits are also kept when you reformat) |
1e400 | Infinity | Number out of range (Python reads inf) |
1e-400 | 0 | Number that becomes 0 |
For large integers you never calculate with, such as order numbers or member numbers, it is safer to exchange them as strings, like "1234567890123456789". RFC 7493 (I-JSON) also recommends putting numbers that need more range or precision than binary64 into strings.
Duplicate keys. RFC 8259 says the keys of an object SHOULD be unique, and adds that when they repeat, some programs keep only the last value, some raise an error and some pass them all on, so the behavior cannot be predicted. JavaScript JSON.parse and Python json use the later value. This validator does not block duplicate keys as errors but flags them as warnings, and when you select such a key in the tree it shows a button that jumps to the earlier key with the same name.
Lone surrogates. A character above U+FFFF, such as an emoji, is a pair of two escapes like \ud83d\ude00. If it was cut in the middle and only \ud83d remains, the syntax still passes, but the result is a character that cannot be converted to UTF-8, and the receiving side shows garbage or raises an error. I-JSON does not allow such characters.
BOM. Editors such as Notepad sometimes put a BOM (U+FEFF) at the very start of a file. RFC 8259 says a BOM MUST NOT be added when sending JSON, and that a reader MAY ignore it. Still, JavaScript JSON.parse and Python json.loads (with string input) treat a BOM as an error. This validator skips the BOM and reads on, flags it as a warning, and leaves it out of reformatted and compacted results.
Key order. In principle the order of keys in a JSON object has no meaning, but the order you wrote matters when a person reads it. A JavaScript object puts integer-like keys such as "2024" before other keys (ECMAScript OrdinaryOwnPropertyKeys). That is why this validator does not use the browser's JSON.parse and draws the tree in the written order with its own parser.
How to read the weight map
The weight map measures the UTF-8 bytes each value directly under the chosen object or array takes up in the source and divides the area in proportion. For an object, it counts the key name, the value and the whitespace between them. The widest cells are laid out first, as close to squares as possible, up to 30 cells, and values below 0.4% of the total are grouped into one hatched 'others' cell. Cell colors match the tree text colors for each type (object, array, string, number, boolean, null).
Click a cell to select that value. If it is an object or an array, it expands in the tree and the map moves one level inside. Click the location trail above the map (All › items › 0) to go back out. In the 'Order API response' example, items, which holds three products, is the widest, and going inside shows the product with many options taking more room. In real responses, base64 images, long descriptions repeated every time and unused debug fields often show up as wide cells.
Common mistakes
- Mistaking a JavaScript object for JSON:
{name: 'a', list: [1, 2,],}written in code is valid in JavaScript but is not JSON. You have to wrap keys and strings in double quotes and delete the trailing commas. Auto-fix handles all three at once. - Copying Python output as it is: the result of
print(dict)uses single quotes and True and None, as in{'ok': True, 'x': None}. If you need JSON, print withjson.dumps(). If you already copied it, auto-fix can convert it. - Backslashes in Windows paths: the
\Uin"C:\Users"is not a JSON escape, so it is an error. Write the backslash twice, as"C:\\Users", or use slashes, as"C:/Users". Folder names that start with\nor\tturn into a line break or tab without any error, so be extra careful. - Numbers versus text that looks like numbers:
42and"42",falseand"false"are different values. In the tree, numbers appear in purple and strings in brown with quotes, so you can check that the type is what you intended. - Checking JSONL as one document: text with one object per line, like a log file, gives the error 'There is more text after the JSON value ended' after the first object. Check it one line at a time or turn it into an array.
- Treating a syntax pass as data validation:
{"age": -5}and{"date": "2026-02-30"}are valid JSON. Required keys, value ranges and whether a date exists must be checked with JSON Schema or the receiving system's validation.
Limits and cautions
- Input up to 5 MB (5,242,880 bytes) is checked. Files are read as UTF-8 (with or without a BOM) or UTF-16 with a BOM. Nesting is read up to 500 levels.
- The tree draws up to 3,000 rows at once, and arrays with many items are expanded 200 at a time with 'Show more'. Find counts up to the first 10,000 matches.
- Column numbers count code points. A character that takes two UTF-16 units, such as an emoji, is one column, so the number can differ from the 'position' in a browser error message, which counts UTF-16 units.
- Auto-fix changes notation only. Some fixes change the meaning, such as turning NaN and Infinity into null, so read the list before you use it. Numbers with leading zeros, doubled commas and truncated documents are not fixed.
- It does not do JSON Schema validation, comparing two JSONs or sorting keys. For more on reformatting and compacting, use a JSON formatter and minifier.
Sources
- 01IETF — RFC 8259: The JavaScript Object Notation (JSON) Data Interchange Format§2 grammar, §4 names SHOULD be unique, §6 binary64 and ±(2⁵³−1) interoperability, §8.1 do not add a BOM and a reader MAY ignore it, §8.2 lone surrogates — checked 2026-10-22
- 02Ecma International — ECMA-404: The JSON data interchange syntaxThe JSON syntax standard (whitespace is only tab, line feed, carriage return and space)
- 03IETF — RFC 7493: The I-JSON Message Format§2.1 no surrogates or noncharacters, §2.2 strings recommended for numbers beyond binary64, §2.3 duplicate names MUST NOT
- 04IETF — RFC 9535: JSONPath: Query Expressions for JSON§2.5.1.1 member-name-shorthand (letters, underscore, characters from U+0080), single-quoted and double-quoted name selectors
- 05IETF — RFC 6901: JavaScript Object Notation (JSON) PointerPaths joined with /, ~ as ~0 and / as ~1, the empty string for the whole document
- 06jq Manual.foo only for keys of letters, digits and underscores, other keys as ."foo" or .["foo"]
- 07Python docs — json: JSON encoder and decoder'Repeated Names Within an Object': only the last value for a name is kept; NaN and Infinity are accepted by default
- 08The JSON5 Data Interchange Format§1.1 extensions beyond JSON: comments, trailing commas, single quotes, identifier keys, hexadecimal, leading and trailing decimal points, + sign, NaN and Infinity
- 09MDN — JSON.parse()Trailing commas and single quotes are a SyntaxError
- 10MDN — Number.MAX_SAFE_INTEGERThe largest integer JavaScript represents exactly, 2⁵³−1 = 9,007,199,254,740,991
- 11ECMAScript Language Specification — OrdinaryOwnPropertyKeys§10.1.11.1 keys shaped like array indexes are listed first, in numeric order
Frequently asked questions
Why is the reported line and column different from where the mistake really is?
The position shown is where the parser could not read any further. For a missing comma it points at the place where the comma belongs, right after the previous value, but a missing closing quote lets the string run on into the next line, so the parser stops after that. Reading the surrounding lines and the 'opened bracket or string start' in the error diagnosis together makes the cause easier to find.
What does auto-fix change?
It handles 12 kinds of notation: comments, trailing commas, commas missing between lines, single-quoted and curly-quoted strings, unquoted keys, True, False, None and uppercase TRUE and NULL, NaN, Infinity and undefined (turned into null), numbers such as +1, .5, 5. and 0x1F, line breaks and tabs inside strings, special spaces, and a leading BOM. It keeps the line layout, changes only those characters, and the button appears only when the fixed result passes the strict check again.
Can I check a JSONC or JSON5 file that has comments?
This validator checks standard JSON (RFC 8259), so comments and trailing commas are shown as errors. Auto-fix can, however, strip comments, trailing commas, single quotes and unquoted keys to produce standard JSON. If the original file will stay JSONC, use the fixed result as a copy to hand to another program.
Why does a big number change to something like 9007199254740992?
JavaScript and many other programs read JSON numbers as IEEE 754 binary64 floating point. That format holds integers exactly only up to ±(2⁵³−1), which is 9,007,199,254,740,991, so a larger integer, or a decimal with more than 17 significant digits, becomes the nearest value. This validator lists the numbers that change in the warnings, together with the value JavaScript reads. For identifiers, sending them as strings is safer.
What happens when the same key appears twice in one object?
RFC 8259 only says keys SHOULD be unique and notes that the behavior for repeats differs between programs. JavaScript JSON.parse and Python json use the later value and discard the earlier one. This validator does not block it as a syntax error but flags it as a warning, and the tree and the reformatted result keep both values.
How do JSONPath and jq paths differ?
JSONPath (RFC 9535) starts with $ and is written like $.items[0].name, and keys with non-ASCII characters such as accents can use dot notation too. jq starts with . and is written like .items[0].name, but dot notation works only for keys of letters, digits and underscores, so a key with an accent or a hyphen is written .["key"]. JSON Pointer (RFC 6901) joins keys with / as in /items/0/name, and writes ~ as ~0 and / as ~1.
What is the size in the weight map based on?
For each value directly under the chosen object or array, it measures the UTF-8 bytes the value takes up in the source (including the key name and whitespace) and divides the area in proportion. It draws up to 30 of the largest cells and groups the very small rest into one 'others' cell. Use it to find why an API response is heavy and which array takes the space.
Is the JSON I enter sent to a server or stored?
No. Pasted text and opened files are checked and converted only inside this browser, and nothing is sent to a server or stored. The address does not contain your content either, so after checking a response that holds tokens or personal data, just close the tab or press Clear.