PHP 8.3 功能: json_validate 函数
PHP 8.3 添加了一个名为 json_validate
的新函数,用来返回 true
或 false
以判断给定的字符串是否是有效的 JSON 字符串。
PHP 8.3 之前,判断给定字符串是不是有效的 JSON 字符串的唯一方法是,尝试解码该字符串,看看是否会产生错误。新的 json_validate
函数底层使用了同一个 JSON 解析器,不过内存使用量更少且像 json_decode
那样处理、只分析字符串,而不去构造任何解码值。
具有防止处理无效 JSON 字符串的强大措施的应用程序,新增的 json_validate
函数可能用处不大。因为 json_validate
在 json_decode
调用后立即执行,会导致 JSON 字符串的分析执行了两次,从而执行时间轻微增加。而且输入的 JSON 字符串是有效的 JSON 的可能性更大。
但是,接收用户提供的 JSON 或连接远程 JSON API 的应用可能会发现新 json_validate
的最佳用途,因为很有可能遇到无效的 JSON 字符串。
json_validate('[1, 2, 3]'); // true
json_validate('{1, 2, 3]'); // false
json_validate
函数摘要
/**
* Validates a given string to be valid JSON.
*
* @param string $json String to validate
* @param int $depth Set the maximum depth. Must be greater than zero.
* @param int $flags Bitmask of flags.
* @return bool True if $json contains a valid JSON string, false otherwise.
*/
function json_validate(string $json, int $depth = 512, int $flags = 0): bool {
}
json_validate
在全局命名空间中声明。- 验证错误可以使用现有的
json_last_error
和json_last_error_msg
函数检索。 - 查看
json_validate
中可接收的 flag。传入无效的 flag 会抛出错误异常。
可以使用 json_decode
函数在用户空间的 PHP 代码中模拟该函数,使之向前兼容。
json_validate
接受的 flag ($flags)
json_validate
函数位操作的 flags,作为其第三个参数 $flags
的值。虽然在后续的 PHP 版本中可能添加其他的 flags, JSON_INVALID_UTF8_IGNORE
是$flags参数目前唯一可接收的 flag 值。
JSON_INVALID_UTF8_IGNORE
是现有的 PHP 常数(从 PHP 7.2 开始),json_decode
函数也可接收该参数。如果传入,json_decode
和 json_validate
函数将在给定的字符串中忽略 UTF-8 字符。
json_validate('[1, 2, 3]', flags: JSON_INVALID_UTF8_IGNORE); // true
json_validate("[\"\xc1\xc1\",\"a\"]"); // false
json_validate("[\"\xc1\xc1\",\"a\"]", flags: JSON_INVALID_UTF8_IGNORE); // true
以上代码使用了PHP 8.0 中添加的命名参数及 16 进制转义序列。
json_validate
验证错误
json_validate()
函数不返回验证错误码(比如语法错误、深度耗尽、不支持类型,等)。不过,现有的 json_last_error
和 json_last_error_msg
函数可用于确定验证错误。
json_validate(""); // false
json_last_error(); // 4
json_last_error_msg(); // "Syntax error"
json_validate("null"); // true
json_last_error(); // 0
json_last_error_msg(); // "No error"
类似于
json_decode
和json_encode
函数,json_validate
通过存储上次操作的错误码来修改应用程序状态,使之不是一个纯函数。虽然这样对大部分 PHP 应用没有显著影响,但可能会出现一些边缘情况,包括在同一线程上服务多个并发请求的某些新 PHP 运行程序上的竞争条件。
用例
以下是 json_validate
的一些用例。他们不会检查在运行的 PHP 版本上是否有 json_validate
函数。
需要支持早于 PHP 8.3 的 PHP 版本的应用程序/包可能需要有条件地使用 json_validate
函数,或者在用户端 PHP 代码中多填充它。
验证给定的 JSON 字符串
json_validate($_GET['json']);
验证给定的 JSON 字符串并抛出异常
本例模拟了 PHP 7.3 中引入的 JSON_THROW_ON_ERROR
flag。
if (json_validate($_GET['json']) === false) {
throw new \JsonException(json_last_error_msg(), json_last_error());
}
使用新增的 json_validate
函数替换现有的 JSON 验证
- $value = json_decode($_GET['json'], flags: JSON_THROW_ON_ERROR);
+ if (!json_validate($_GET['json'])) {
+ throw new \JsonException(json_last_error_msg(), json_last_error());
+ }
+ $value = json_decode($_GET['json']);
用户空间填充
json_validate()
函数的内部实现消费了更少的内存和处理,这是 json_validate
函数的主要优势。可以通过观察 json_decode
生成的错误码,在 PHP 用户空间中进行编码模拟填充,不过这种模拟在实际实现中并没有内存/处理上的改进。
if (!function_exists('json_validate')) {
function json_validate(string $json, int $depth = 512, int $flags = 0): bool {
if ($flags !== 0 && $flags !== \JSON_INVALID_UTF8_IGNORE) {
throw new \ValueError('json_validate(): Argument #3 ($flags) must be a valid flag (allowed flags: JSON_INVALID_UTF8_IGNORE)');
}
if ($depth <= 0 ) {
throw new \ValueError('json_validate(): Argument #2 ($depth) must be greater than 0');
}
\json_decode($json, null, $depth, $flags);
return \json_last_error() === \JSON_ERROR_NONE;
}
}
以上代码在 PHP 8.0 之后的版本可用。如果 \ValueError
异常使用其他类型的异常替代,可以兼容至 PHP ≥ 7.3 。
向后兼容影响
json_validate()
是 PHP 8.3 上添加的新函数。现有的 PHP 应用在全局命名空间中声明 json_validate
函数会在 PHP 8.3 中造成重复声明错误。
该函数可以使用用户空间的 PHP 代码实现,尽管不会带来实际 json_validate
函数提供的内存/处理上的优势。