验证JSON的Regex有什么推荐?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (16)

我正在寻找允许我验证json的正则表达式。

我对Regex很新,我知道用Regex解析不好,但可以用它来验证吗?

提问于
用户回答回答于

(这个正则表达式是从证明反对者错误的部门给你带来的。)

是的,一个完整的正则表达式验证是可能的。

大多数现代正则表达式实现允许递归regexpressions,它可以验证完整的JSON序列化结构。该json.org规范使得它非常简单。

$pcre_regex = '
  /
  (?(DEFINE)
     (?<number>   -? (?= [1-9]|0(?!\d) ) \d+ (\.\d+)? ([eE] [+-]? \d+)? )    
     (?<boolean>   true | false | null )
     (?<string>    " ([^"\\\\]* | \\\\ ["\\\\bfnrt\/] | \\\\ u [0-9a-f]{4} )* " )
     (?<array>     \[  (?:  (?&json)  (?: , (?&json)  )*  )?  \s* \] )
     (?<pair>      \s* (?&string) \s* : (?&json)  )
     (?<object>    \{  (?:  (?&pair)  (?: , (?&pair)  )*  )?  \s* \} )
     (?<json>   \s* (?: (?&number) | (?&boolean) | (?&string) | (?&array) | (?&object) ) \s* )
  )
  \A (?&json) \Z
  /six   
';

它使用PCRE功能在PHP中运行得非常好。应该在Perl中不加修改地工作; 并且当然可以适用于其他语言。此外,它还成功地使用了JSON测试用例

更简单的RFC4627验证

更简单的方法是RFC4627第6节中规定的最小一致性检查。但它只是作为安全测试和基本的无效预防措施:

  var my_JSON_object = !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
         text.replace(/"(\\.|[^"\\])*"/g, ''))) &&
     eval('(' + text + ')');
用户回答回答于

是的,正则表达式只能匹配常规语言是一种常见的误解。实际上,PCRE函数可以比常规语言匹配得多,甚至可以匹配一些非上下文无关的语言!维基百科关于RegExps的文章有一个特别的章节。

使用PCRE可以以多种方式识别JSON!@mario使用命名的子模式和反向引用展示了一个很好的解决方案。然后他指出应该有一个使用递归模式 的解决方案(?R)。这里是用PHP编写的这样的正则表达式的例子:

$regexString = '"([^"\\\\]*|\\\\["\\\\bfnrt\/]|\\\\u[0-9a-f]{4})*"';
$regexNumber = '-?(?=[1-9]|0(?!\d))\d+(\.\d+)?([eE][+-]?\d+)?';
$regexBoolean= 'true|false|null'; // these are actually copied from Mario's answer
$regex = '/\A('.$regexString.'|'.$regexNumber.'|'.$regexBoolean.'|';    //string, number, boolean
$regex.= '\[(?:(?1)(?:,(?1))*)?\s*\]|'; //arrays
$regex.= '\{(?:\s*'.$regexString.'\s*:(?1)(?:,\s*'.$regexString.'\s*:(?1))*)?\s*\}';    //objects
$regex.= ')\Z/is';

我使用的(?1)不是(?R)因为后者引用了整个模式,而是我们有\A和子\Z序列中不应该使用的序列。(?1)对由最外括号标记的正则表达式的引用(这就是为什么最外层( )不以其开头?:)。所以,RegExp变成268个字符:)

/\A("([^"\\]*|\\["\\bfnrt\/]|\\u[0-9a-f]{4})*"|-?(?=[1-9]|0(?!\d))\d+(\.\d+)?([eE][+-]?\d+)?|true|false|null|\[(?:(?1)(?:,(?1))*)?\s*\]|\{(?:\s*"([^"\\]*|\\["\\bfnrt\/]|\\u[0-9a-f]{4})*"\s*:(?1)(?:,\s*"([^"\\]*|\\["\\bfnrt\/]|\\u[0-9a-f]{4})*"\s*:(?1))*)?\s*\})\Z/is

无论如何,这应该被视为“技术示范”,而不是一个实际的解决方案。在PHP中,我将通过调用json_decode()函数来验证JSON字符串。如果我要使用该JSON(如果它被验证),那么这是最好的方法。

扫码关注云+社区