You paste a chunk of JSON into your code or API request and get a cryptic parse error. Or you receive data from an external source and need to confirm it's well-formed before processing it. Either way, the problem is the same: JSON looks deceptively simple until something breaks.
This guide explains the most common JSON errors, how to fix them, and how to validate JSON programmatically in JavaScript, Python, Go, and PHP.
Why JSON validation matters
JSON (JavaScript Object Notation) has a strict grammar defined in RFC 8259. Unlike YAML or TOML, it has no forgiving fallbacks — one stray comma or unquoted key, and the entire document is rejected. A validator confirms that a string is syntactically correct JSON before you hand it to your application code.
Two situations where validation is non-negotiable:
- User-supplied or third-party data — you can't trust it without checking.
- Manually edited config files — human fingers introduce trailing commas and comments.
The seven most common JSON errors
| Error | What it looks like | Fix |
|---|---|---|
| Trailing comma | {"a": 1,} |
Remove the comma before } or ] |
| Single quotes | {'key': 'val'} |
Use double quotes: {"key": "val"} |
| Unquoted key | {key: "value"} |
Quote the key: {"key": "value"} |
| Comment | // this is config |
Remove — JSON has no comments |
| Undefined/NaN | {"n": NaN} |
Use null or a number literal |
| Bare string | hello world |
Wrap in quotes or object braces |
| Mismatched brackets | {"a": [1, 2} |
Ensure every [ closes with ] |
Trailing comma
The most common mistake when editing JSON by hand:
// INVALID
{
"name": "Alice",
"age": 30,
}
// VALID
{
"name": "Alice",
"age": 30
}
JavaScript (and many JSON5 parsers) accept trailing commas, which trains developers to write them habitually — then their JSON breaks when a strict parser processes it.
Single quotes
JSON requires double quotes for strings and keys. Single quotes produce a syntax error even though JavaScript itself accepts them:
// INVALID
{'name': 'Alice'}
// VALID
{"name": "Alice"}
Comments
JSON has no comment syntax. Adding them is invalid:
// INVALID
{
// database host
"host": "localhost"
}
If you need comments in a config file, consider JSONC (supported by VS Code and TypeScript's tsconfig.json), YAML, or TOML instead.
Validate JSON in JavaScript
JSON.parse() throws a SyntaxError on invalid input. Wrap it in a try/catch:
function isValidJSON(str) {
try {
JSON.parse(str);
return true;
} catch {
return false;
}
}
// With error message
function validateJSON(str) {
try {
const parsed = JSON.parse(str);
return { valid: true, data: parsed, error: null };
} catch (err) {
return { valid: false, data: null, error: err.message };
}
}
const result = validateJSON('{"name": "Alice", "age": 30}');
// { valid: true, data: { name: 'Alice', age: 30 }, error: null }
const bad = validateJSON("{'name': 'Alice'}");
// { valid: false, data: null, error: "Expected property name or '}' in JSON at position 1" }
For schema validation (checking that keys exist and values have the right types), use a library like Ajv:
import Ajv from 'ajv';
const ajv = new Ajv();
const schema = {
type: 'object',
properties: {
name: { type: 'string' },
age: { type: 'integer', minimum: 0 }
},
required: ['name', 'age'],
additionalProperties: false
};
const validate = ajv.compile(schema);
const data = { name: 'Alice', age: 30 };
if (!validate(data)) {
console.error(validate.errors);
}
Validate JSON in Python
Python's json module raises json.JSONDecodeError (a subclass of ValueError) for invalid JSON:
import json
def is_valid_json(text: str) -> bool:
try:
json.loads(text)
return True
except json.JSONDecodeError:
return False
def validate_json(text: str) -> dict:
try:
data = json.loads(text)
return {"valid": True, "data": data, "error": None}
except json.JSONDecodeError as e:
return {
"valid": False,
"data": None,
"error": f"{e.msg} (line {e.lineno}, col {e.colno})"
}
result = validate_json('{"name": "Alice", "age": 30}')
# {'valid': True, 'data': {'name': 'Alice', 'age': 30}, 'error': None}
bad = validate_json("{'name': 'Alice'}")
# {'valid': False, 'data': None, 'error': "Expecting property name enclosed in double quotes (line 1, col 2)"}
Note that Python's json.JSONDecodeError includes line number and column, which makes it easier to pinpoint the error in large documents.
For schema validation, use jsonschema:
from jsonschema import validate, ValidationError
import json
schema = {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer", "minimum": 0}
},
"required": ["name", "age"]
}
data = json.loads('{"name": "Alice", "age": 30}')
try:
validate(instance=data, schema=schema)
print("Valid")
except ValidationError as e:
print(f"Invalid: {e.message}")
Validate JSON in Go
Go's encoding/json package provides json.Valid() for a quick syntactic check, plus json.Unmarshal() for a full parse:
package main
import (
"encoding/json"
"fmt"
)
// Quick syntax check — no allocation
func isValidJSON(b []byte) bool {
return json.Valid(b)
}
// Full parse with error details
func validateJSON(input string) (map[string]any, error) {
var result map[string]any
if err := json.Unmarshal([]byte(input), &result); err != nil {
return nil, err
}
return result, nil
}
func main() {
good := []byte(`{"name":"Alice","age":30}`)
fmt.Println(json.Valid(good)) // true
bad := []byte(`{'name':'Alice'}`)
fmt.Println(json.Valid(bad)) // false
data, err := validateJSON(`{"name":"Alice","age":30}`)
if err != nil {
fmt.Println("Parse error:", err)
} else {
fmt.Println("Parsed:", data)
}
}
json.Valid() is efficient — it checks the syntax without building a Go value — making it suitable for validating many documents in a loop.
For strict schema validation in Go, use gojsonschema or jsonschema.
Validate JSON in PHP
PHP's json_decode() returns null on failure. Check json_last_error() to distinguish between a null literal and a parse error:
<?php
function isValidJson(string $input): bool {
json_decode($input);
return json_last_error() === JSON_ERROR_NONE;
}
function validateJson(string $input): array {
$data = json_decode($input, true);
$error = json_last_error();
if ($error !== JSON_ERROR_NONE) {
return [
'valid' => false,
'data' => null,
'error' => json_last_error_msg(),
];
}
return ['valid' => true, 'data' => $data, 'error' => null];
}
$good = validateJson('{"name":"Alice","age":30}');
// ['valid' => true, 'data' => ['name' => 'Alice', 'age' => 30], 'error' => null]
$bad = validateJson("{'name':'Alice'}");
// ['valid' => false, 'data' => null, 'error' => 'Syntax error']
?>
PHP 7.3+ also accepts JSON_THROW_ON_ERROR to throw a JsonException instead of setting the error code:
<?php
function validateJsonStrict(string $input): mixed {
return json_decode($input, true, 512, JSON_THROW_ON_ERROR);
}
try {
$data = validateJsonStrict('{"name":"Alice"}');
} catch (\JsonException $e) {
echo "JSON error: " . $e->getMessage();
}
?>
Syntax check vs schema validation
Syntax validation and schema validation solve different problems:
| Syntax check | Schema validation | |
|---|---|---|
| What it checks | Is this valid JSON? | Does it have the right shape? |
| What it rejects | Malformed JSON | Missing keys, wrong types, extra fields |
| Speed | Very fast | Slower (validates every field) |
| Libraries | Built-in parsers | Ajv, jsonschema, gojsonschema |
| Use case | Input sanitisation | API contract enforcement |
Always do the syntax check first — schema validators assume they're receiving valid JSON.
Quick reference: validation methods
| Language | Syntax check | Schema validation |
|---|---|---|
| JavaScript | JSON.parse() in try/catch |
Ajv |
| Python | json.loads() → catch JSONDecodeError |
jsonschema |
| Go | json.Valid() or json.Unmarshal() |
gojsonschema, santhosh-tekuri/jsonschema |
| PHP | json_decode() + json_last_error() |
justinrainbow/json-schema |
| CLI | python -m json.tool, jq . |
— |
| Browser | DevTools console JSON.parse(...) |
— |
6 common mistakes when validating JSON
Checking only the return value, not the error code (PHP).
json_decode()returnsnullfor bothnullliterals and parse errors. Always checkjson_last_error()or useJSON_THROW_ON_ERROR.Catching
Exceptioninstead ofSyntaxError(JavaScript).JSON.parse()throwsSyntaxError, not a genericError. CatchingExceptionin typed languages or being too broad in the catch block can hide which error occurred.Confusing syntax validity with semantic validity. A document can be syntactically valid JSON but semantically wrong for your application — a string where you expect a number, a missing required field. Use schema validation for semantic checks.
Not validating at the boundary. Validate external JSON (API responses, user uploads, form data) as soon as it enters your application. Don't wait until you try to use a field and get a nil-pointer or key-error.
Editing JSON by hand in an editor without a linter. Install a JSON or JSONC plugin in VS Code / JetBrains. Inline error highlighting catches trailing commas, mismatched brackets, and bad types before you even hit save.
Using
eval()as a JSON parser (JavaScript).eval('(' + input + ')')parses JSON-like strings but also executes arbitrary JavaScript. Always useJSON.parse()for security.
Frequently asked questions
Can JSON contain comments?
No. The JSON specification (RFC 8259) does not include comments. If you need comments in a config file, switch to JSONC, YAML, or TOML. JSONC is a superset of JSON that allows // and /* */ comments; it's supported by VS Code, TypeScript's tsconfig.json, and some other tools.
What's the difference between JSON.parse() and JSON.stringify()?
JSON.parse() converts a JSON string into a JavaScript value (parsing). JSON.stringify() does the opposite: it converts a JavaScript value into a JSON string (serialisation). Validation uses parse() — if it throws, the input isn't valid.
Why does my JSON validate in the browser but fail on the server? Usually a character encoding issue. The browser may handle a UTF-8 BOM (byte order mark) silently, while a strict server parser rejects it. Strip the BOM before sending. Another common cause: the server receives the body as bytes; ensure you're decoding it as UTF-8 before calling the parser.
Is null valid JSON?
Yes. A bare null is valid JSON. So is a bare string ("hello"), a number (42), and a boolean (true). JSON's root value doesn't have to be an object or array — though in practice, root-level objects and arrays are the norm.
How do I validate a JSON file from the command line? Two easy options:
# Python (built-in)
python -m json.tool input.json > /dev/null && echo "valid" || echo "invalid"
# jq (if installed)
jq . input.json > /dev/null && echo "valid" || echo "invalid"
Both exit with a non-zero status on invalid input, making them scriptable.
What is JSON Schema? JSON Schema is a vocabulary (also expressed in JSON) that describes the structure and constraints of a JSON document — required fields, types, minimum/maximum values, patterns, and more. A schema validator like Ajv (JS) or jsonschema (Python) loads your schema and checks that a given JSON document conforms to it. It's the standard way to enforce API contracts and validate complex data at the boundary.