JSON Validator
Every error with its exact line, column, cause and fix.
Nothing you paste leaves your browser. The connect-src allowlist makes that a browser guarantee rather than a promise. Check it yourself
Validation answers one question: is this a legal JSON document? The useful part is what happens when the answer is no. Most validators tell you a token was unexpected and leave you to find it. This one tells you which character, on which line and column, what it expected instead, and what to do about it.
It also does not stop at the first problem. A document with four mistakes reports four mistakes, so you fix them in one pass rather than four.
What is checked
The grammar of RFC 8259, in full. That includes the parts people are surprised by.
- Whitespace
- Exactly four characters are legal between tokens: space, tab, carriage return and line feed. A no-break space, a zero-width space or an ideographic space is a syntax error, and this validator names the character rather than reporting an unexpected token. These arrive constantly from copying JSON out of a web page, a PDF or a chat client.
- Numbers
- No leading zeros, no leading plus, no hexadecimal, no trailing decimal point, no NaN and no Infinity. Each violation gets its own message, because each has a different cause and a different fix.
- Strings
- Only nine escape sequences are legal. Control characters below U+0020 must be escaped. Lone surrogates are flagged as a warning, because they parse but do not survive re-encoding to UTF-8.
- One top-level value
- A document holds exactly one. Several values one per line is NDJSON, and this validator recognises that shape and says so instead of reporting a generic trailing-content error.
Warnings, which are not errors
Some things parse but will still ruin your afternoon. They are reported separately so they never block your output.
- Duplicate keys
- RFC 8259 says keys SHOULD be unique and leaves the behaviour undefined when they are not. JavaScript and Python keep the last one, some Go and Java parsers reject the document, and a few keep the first. You get the position of both.
- Integers outside the safe range
- Above 2^53-1 a JavaScript number cannot hold the value exactly. The warning names the value JSON.parse would give you instead.
- A byte order mark
- A leading U+FEFF is accepted here and reported, because JSON.parse in browsers and Node rejects it outright.
- Very deep nesting
- This parser is iterative and has no depth limit, but plenty of consumers do. Measured on this machine, V8 refuses to serialise a structure deeper than about 4,800 levels, so a document you can read may still be one you cannot write back out.
Validating shape as well as syntax
Syntax validation only tells you the document is well-formed, not that it contains what you expected. For that you need JSON Schema, which describes required properties, types and constraints. Our schema generator produces a starting point from a sample payload.
How to do this in code
Checking validity in code, and getting a useful error out of it.
js JavaScript
There is no non-throwing validator in the standard library, so the try/catch is the API.
function validate(text) {
try {
JSON.parse(text);
return { ok: true };
} catch (e) {
// Modern V8 includes a (line L column C) suffix in the message.
return { ok: false, message: e.message };
}
} py Python
JSONDecodeError carries msg, lineno, colno, pos and doc, which is more structure than most runtimes give you.
import json
try:
json.loads(text)
except json.JSONDecodeError as e:
print(f"{e.msg} at line {e.lineno} column {e.colno} (char {e.pos})") sh Shell
jq empty parses the input and outputs nothing, which makes it a clean validity check in a CI script.
# jq exits non-zero and prints the position on failure
jq empty input.json
# Python, no extra install
python -m json.tool input.json > /dev/null go Go
Go reports a byte offset rather than a line, so you have to count newlines yourself.
if !json.Valid(data) {
// Valid() gives no position. To get one, decode and
// inspect the SyntaxError:
var v any
if err := json.Unmarshal(data, &v); err != nil {
var se *json.SyntaxError
if errors.As(err, &se) {
line := 1 + bytes.Count(data[:se.Offset], []byte("\n"))
return fmt.Errorf("%v at line %d", se, line)
}
}
} Questions
- Why does it report several errors when other validators report one?
- Because the parser recovers rather than stopping. After reporting a problem it resynchronises and carries on, so a document with a trailing comma, a single-quoted string and an unquoted key reports all three in one pass.
- Is a bare string or number valid JSON on its own?
- Yes, since RFC 7159 in 2014. The original RFC 4627 required the top-level value to be an object or an array; the current specification, RFC 8259, allows any value. So "hello", 42 and null are all complete, valid JSON documents.
- Are trailing commas ever allowed?
- Not in JSON. They are allowed in JavaScript, in JSON5 and in JSONC, which is what VS Code uses for its own settings files. If your consumer accepts JSONC you can keep them; otherwise the repair tool strips them.
- What about comments?
- JSON has none by design. Douglas Crockford removed them deliberately, on the grounds that people were using them to hold parsing directives. Use JSONC or JSON5, or move the note into a key such as "_comment".