Statement on glibc/iconv Vulnerability

json_validate

(PHP 8 >= 8.3.0)

json_validate文字列が有効なJSONかどうかを調べる

説明

json_validate(string $json, int $depth = 512, int $flags = 0): bool

指定された文字列が、文法的に有効なJSONかどうかを返します。 json_validate()true を返す場合、 同じ depthflags を指定して json_decode() を実行してもデコードは成功します。

json_validate()false を返す場合、 原因は json_last_error()json_last_error_msg() を使って取得できます。

デコードされたJSONペイロードを使わない場合、 json_validate()json_decode() よりもメモリ使用量が少なくなります。 なぜなら、ペイロードを含む配列やオブジェクト構造を組み立てる必要がないからです。

警告

 json_decode() の直前に json_validate() をコールすると、 文字列を不必要に2回パースすることになります。 なぜなら、json_decode() はデコードしている間に暗黙のうちに文字列を検証するからです。

よって json_validate() は、JSON のペイロードをすぐに使わない場合、かつ有効なJSON文字列かどうかを知る必要がある場合にのみ使うべきです。

パラメータ

json

検証する文字列

この関数は、UTF-8 でエンコードされた文字列でのみ動作します。

注意:

PHP の実装は、 » RFC 7159 の JSON のスーパーセットです。

depth

デコードされるネスト構造の深さの最大値。 この値は 0 より大きく、 2147483647 以下でなければいけません。

flags

現状は、JSON_INVALID_UTF8_IGNORE のみを受け入れます。

戻り値

指定された文字列が文法的に有効なJSONの場合、true を返します。 そうでない場合、false を返します。

エラー / 例外

depth が許可された範囲外の値の場合、 ValueError がスローされます。

flags が有効なフラグでない場合、 ValueError がスローされます。

例1 json_validate() の例

<?php
var_dump
(json_validate('{ "test": { "foo": "bar" } }'));
var_dump(json_validate('{ "": "": "" } }'));
?>

上の例の出力は以下となります。

bool(true)
bool(false)

参考

add a note

User Contributed Notes 3 notes

up
12
Behrad
3 months ago
---------------- PHP < 8.3 ----------------

function json_validate(string $string): bool {
json_decode($string);

return json_last_error() === JSON_ERROR_NONE;
}

var_dump(json_validate('{ "test": { "foo": "bar" } }')); // true

---------------- PHP >= 8.3 ----------------

var_dump(json_validate('{ "test": { "foo": "bar" } }')); // true

Note: code from https://www.php.net/releases/8.3/en.php
up
4
Julien T.
2 months ago
Building upon Allan R.'s initial idea, I've developed an improved version of the json_validate function for those using PHP 8.2 and earlier versions. This function emulates the functionality introduced in PHP 8.3, providing an effective way to validate JSON strings in earlier PHP versions.

```php
if (!function_exists('json_validate')) {
/**
* Validates a JSON string.
*
* @param string $json The JSON string to validate.
* @param int $depth Maximum depth. Must be greater than zero.
* @param int $flags Bitmask of JSON decode options.
* @return bool Returns true if the string is a valid JSON, otherwise false.
*/
function json_validate($json, $depth = 512, $flags = 0) {
if (!is_string($json)) {
return false;
}

try {
json_decode($json, false, $depth, $flags | JSON_THROW_ON_ERROR);
return true;
} catch (\JsonException $e) {
return false;
}
}
}
```

Key Improvements:

- String Check: Added a validation to ensure the input is a string.
- Error Handling: Utilizes try-catch to effectively catch and handle JsonException.
- Backward Compatibility: Safely integrable in older PHP versions, automatically deferring to native functionality in PHP 8.3+.
up
1
Allan R.
2 months ago
Pre PHP 8.3, and future compatible, function/wrapper

---
if(!function_exists("json_validate")) {
function json_validate() {
try {
json_decode($json, JSON_THROW_ON_ERROR);
return true;
} catch(\JsonException) {
return false;
}
}
}
---

An issue with simply relying on json_last_error() == JSON_ERROR_NONE is if you have an error handler that catches errors or notices and throws them instead as fx. \ErrorException

That would cause a call to json_decode(); to throw an exception exiting the scope of the function.
To Top