[PHP8.3] 能够判断JSON是否正确
PHP8.2 尚未发布,但将在 PHP8.3 中引入的一项功能已经提前确定。
所以下面是相关的RFC,PHP RFC:json_validate这是一个介绍。
PHP RFC:json_validate
介绍
这个 RFC 引入了一个函数 json_validate()
,它验证一个字符串是一个有效的 JSON 字符串。
同一个函数的大部分用户态实现都使用json_decode()
,它在解析字符串时会生成ZVAL,如果只是为了验证会浪费不必要的处理和浪费内存。
json_validate()
使用 PHP 核心中存在的 JSON 解析器。
这与json_decode()
使用的相同,因此json_validate()
有效的任何字符串都保证为json_decode()
。
提议
描述
json_validate(string $json, int $depth = 512, int $flags = 0): bool
参数
$json
目标 JSON 字符串。
只有 UTF-8 对字符代码有效。
$深度
最大嵌套深度。
$标志
目前JSON_INVALID_UTF8_IGNORE已验证。
返回值
如果传递的字符串作为 JSON 有效,则返回 true,否则返回 false。
例子
var_dump(json_validate('{ "test": { "foo": "bar" } }'));
结果将是真实的。
var_dump(json_validate('{ "": "": "" } }'));
将是错误的。
原因是json_last_error()或者json_last_error_msg()可以在
RFC 讨论的一般说明
从 RFC 讨论中吸取的教训。
・许多用户已经测试过此功能并能够得到预期的结果。
• 社区中的大多数人都对该RFC 持积极态度。
・代码审阅者表示,代码体积小,易于维护,好处多多。
- 在 RFC 讨论期间,我们从社区收到了很多有用的反馈。
社区贡献的用例
社区提交的用例。
除了这个例子,很多用户也提供了反馈。
• 来自可信来源的 JSON 格式正确且不是很大。但是您的验证函数还需要能够处理未格式化的 JSON。
- 这不是一个很好的补充,因为它可以防止一些针对 JSON 的 DoS 攻击?
在核心中有 json_validate() 函数的原因
为什么这个函数应该在 PHP 核心中。
使用 json_decode 仅验证 json-string 的缺点
json_decode 在解析时会创建一个 ZVAL 结构,因此对内存和处理速度不友好。
使用正则表达式的缺点
使用正则表达式使维护变得困难。
用户态解决方案的缺点
在用户空间中编写 JSON 解析器并不容易。
此外,用户空间实现和 json_decode 结果可能不同。
首先,PHP 已经有一个 JSON 解析器,所以在用户空间中实现它是一件麻烦事。
PHP 已经有一个 JSON 解析器
由于 PHP 从一开始就有 JSON 解析器,所以它是安全的,因为它与 json_decode 100% 兼容。
主要项目和开发商的需求
来自主要项目和开发商的要求。
以下是可以从该功能中受益的主要项目列表。
另外,这里有一个指向需要此功能的 StackOverflow 的链接。
核心中增加了复杂性
目前 PHP 核心中存在 JSON 解析器,json_decode()
只是在使用它。
因此,没有必要为此 RFC 引入新的 JSON 解析器。
新函数将只使用现有的 JSON 解析器来解析字符串,而无需创建对象或类似的东西。
讨论期间发生的 RFC 更改
部分因 RFC 讨论而改变。
出错时抛出异常
在最初的实现中,有一个标志指定如果在验证期间发生错误是否抛出异常。
由于代码审查无法理解此类行为,因此已从实现中删除了在错误时引发异常的能力。
其他
RFC 中描述的三个示例被删除,因为它们不符合 RFC 的意图或毫无意义。
使用json_decode()
的缺点改变了措辞.
向后不兼容的更改
没有向后不兼容的更改。
函数名称json_validate()
不能在用户空间中使用。
建议的 PHP 版本
PHP8.3
RFC 影响
此 RFC 不影响 SAPI、现有扩展、OPCache 等。
执行
参考
将从中受益的主要开源项目
主要 OSS 项目可获得的好处。
class JsonValidator extends ConstraintValidator
public function validateJson($attribute, $value)
{
if (is_array($value)) {
return false;
}
if (! is_scalar($value) && ! is_null($value) && ! method_exists($value, '__toString')) {
return false;
}
json_decode($value);
return json_last_error() === JSON_ERROR_NONE;
}
protected function isValidJsonValue($value)
{
if (in_array($value, ['null', 'false', '0', '""', '[]'])
|| (json_decode($value) !== null && json_last_error() === JSON_ERROR_NONE)
) {
return true;
}
//JSON last error reset
json_encode([]);
return false;
}
public static function validateJson($value, $params)
{
return (bool) (@json_decode($value));
}
final class Json extends AbstractRule
{
/**
* {@inheritDoc}
*/
public function validate($input): bool
{
if (!is_string($input) || $input === '') {
return false;
}
json_decode($input);
return json_last_error() === JSON_ERROR_NONE;
}
}
public static function isJson($string)
{
json_decode($string);
return json_last_error() == JSON_ERROR_NONE;
}
function is_json( $argument, $ignore_scalars = true ) {
if ( ! is_string( $argument ) || '' === $argument ) {
return false;
}
if ( $ignore_scalars && ! in_array( $argument[0], [ '{', '[' ], true ) ) {
return false;
}
json_decode( $argument, $assoc = true );
return json_last_error() === JSON_ERROR_NONE;
}
if (is_string($value)) {
json_decode($value); //<------ HERE
// Check if value is a valid JSON string.
if ($value !== '' && json_last_error() !== JSON_ERROR_NONE) {
/**
* If the value is not empty and is not a valid JSON string,
* it is most likely a custom field created in Joomla 3 and
* the value is a string that contains the file name.
*/
if (is_file(JPATH_ROOT . '/' . $value)) {
$value = '{"imagefile":"' . $value . '","alt_text":""}';
} else {
$value = '';
}
}
与此相关的 Stackoverflow 问题
Python中的一个类似问题:如何在 Python 中检查字符串是否是有效的 JSON?
Java中的类似问题:检查文件是否为 json、java
投票
以 2/3 的赞成票通过。
投票期为 22/09/2022 至 07/10/2022。
该 RFC 获得了 18 票赞成和 1 票反对的多数票。
想法
该 RFC 最初是无论如何,如果它的格式正确,json_decode它,那为什么不从头开始json_decode呢?有一些人是这样的,但由于提议者的不断说服和提供各种用例,它被成功采用。
我不确切知道它会快多少或节省多少内存,但通过将处理从 PHP 更改为 native 可能会大大改善。
失败时获取错误内容json_last_error我必须使用JSON_THROW_ON_ERROR我不太明白为什么它不支持 .
原创声明:本文系作者授权爱码网发表,未经许可,不得转载;
原文地址:https://www.likecs.com/show-308630483.html
- 上一篇 »PHP判断是否都是中文
- 下一篇 »Linux学习 - 条件判断