json_validate
Checks whether a string contains syntactically valid JSON without building the decoded value.
json_validate(string $json, int $depth = 512, int $flags = 0): bool- Added in PHP 8.3.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$json | string | The string to validate. Must be valid UTF-8. |
$depthoptional | int= 512 | Maximum nesting depth of the structure being validated. Must be greater than 0 and at most 2147483647. |
$flagsoptional | int= 0 | Currently only JSON_INVALID_UTF8_IGNORE is accepted. Any other flag is rejected. |
Return value
booltrue if the string is syntactically valid JSON within the given depth, otherwise false.
Errors
Throws ValueError when depth is outside the range 1 to 2147483647, or when flags contains anything other than JSON_INVALID_UTF8_IGNORE.
json_validate, added in PHP 8.3, answers one question: is this string parseable JSON? It runs the same parser as json_decode() but never allocates the resulting arrays or objects, so it uses far less memory on large payloads. When it returns true, json_decode() with the same depth and flags is guaranteed to succeed.
When it actually helps
Reach for it when you want to check a payload and then not use it: rejecting a bad request body early, filtering a batch of log lines, verifying a JSON column during a migration, or letting a user paste JSON into a form field and telling them it is malformed. In all of these the decoded value is never needed.
Do not put it directly in front of json_decode(). That parses the same string twice for no benefit, because decoding already validates. The idiomatic single-pass check is json_decode($s, true, 512, JSON_THROW_ON_ERROR) inside a try block.
Note that it checks syntax only. A string can be perfectly valid JSON and still be missing every field your code expects, or be an array where you wanted an object — schema validation is a separate job. On failure, json_last_error_msg() tells you why.
Example
When to use it
- Reject a malformed request body with a 400 before any further processing.
- Filter a large JSON Lines export, counting corrupt records without loading them.
- Validate a JSON column during a database migration without materialising each row.
- Give instant feedback on a textarea where a user pastes a JSON configuration.
Frequently asked questions
What is the difference between json_validate and json_decode?
json_validate only reports whether the string parses and returns a bool, while json_decode also builds the PHP value. Validating is cheaper in memory because no arrays or objects are allocated, but if you need the data anyway, just decode.
Should I call json_validate before json_decode?
No. json_decode validates as it parses, so doing both means parsing the same string twice. Use json_decode with JSON_THROW_ON_ERROR in a try/catch instead.
How do I check for valid JSON on PHP 8.2 or older?
json_validate was added in PHP 8.3, so on older versions call json_decode and then test json_last_error() === JSON_ERROR_NONE, ideally wrapped in a function_exists polyfill so the calling code stays the same.
More examples
Screening a batch of records
Lines 2 and 4 fail: one has a missing value, the other uses single quotes, which JSON does not allow. Because json_validate takes a string and returns a bool, it plugs straight into array_filter as a callback, and no decoded structure is ever built for the 4 records.
<?php
$lines = [
'{"id":1,"ok":true}',
'{"id":2,"ok":}',
'[1,2,3]',
"{'id':4}",
];
foreach ($lines as $i => $line) {
printf("line %d: %s\n", $i + 1, json_validate($line) ? 'valid' : 'INVALID');
}
echo 'valid count: ', count(array_filter($lines, 'json_validate')), "\n";Syntax valid does not mean usable
The string parses without complaint, so json_validate returns true, yet the field the application needs is misspelled and absent. Validation and schema checking are separate steps: use json_validate for the parser's opinion and your own code for the contract.
<?php
$payload = '{"nmae":"Ada"}'; // typo in the key
var_dump(json_validate($payload));
$data = json_decode($payload, true);
if (!isset($data['name'])) {
echo "valid JSON, but the 'name' field is missing\n";
}
print_r(array_keys($data));A polyfill for PHP 8.2 and older
On PHP 8.3 and up the native function already exists and the shim is skipped, so the same code runs everywhere. On older versions the fallback decodes and throws the result away — correct, but without the memory saving that makes the real function worth using.
<?php
if (!function_exists('json_validate')) {
function json_validate(string $json, int $depth = 512, int $flags = 0): bool {
json_decode($json, null, $depth, $flags);
return json_last_error() === JSON_ERROR_NONE;
}
}
var_dump(json_validate('{"a":[1,2]}'));
var_dump(json_validate('{"a":[1,2}'));
Discussion