Regex表达式从长字符串中检索所有JSON

时间:2017-09-05 12:22:13

标签: json regex

我有一个包含许多JSON的长字符串,它看起来像:

{"a":"b"}{"c":"d"}{"e":"f"}...

我准备了regex表达式来从这种字符串中检索所有JSON:

\{(?:[^{}]|(?R))*\}

它工作得很好,但它有一个问题。如果在需要检索如下字符串时失败:

{"a":"b"}{"c":"d"}{"e":"f}"}...

它假定,"}" " f"之后的标志字母结束了第三个JSON,但当然不是。你有没有人知道如何解决这个问题?

代码示例: https://regex101.com/r/L9UUzj/1

谢谢!

1 个答案:

答案 0 :(得分:2)

[^{}]不会考虑引号之间的部分,而是可以将其替换为:[^"{}]|"[^"]*"

您可以使用此模式执行此操作:

{[^"{}]*+(?:"[^"]*+"[^"{}]*+|(?R)[^"{}]*+)*+}

demo

此外,如果您想在引用的部分内处理转义引号(带反斜杠):

{[^"{}]*+(?:"[^"\\]*+(?s:\\.[^"\\]*)*+"[^"{}]*+|(?R)[^"{}]*+)*+}

demo

这两种模式使用更高效的展开设计。简而言之,您不必编写(A|B)*,而是编写需要较少步骤的A*(BA*)*

当大括号在字符串中的位置不平衡时,占有量词*+可以防止大量回溯。这样,模式在这个位置会很快失败。

显然,这两种模式并没有完全描述json语法。可以使用命名组和(?(DEFINE)...)功能来做到这一点,这远非不可能(*)。但是你也可以使用第二种模式来提取json子串,然后用你选择的json解析器检查它们。

(*)这样的事情:

~
\g<object>

(?(DEFINE)
    (?<string> " [^"\\]*+ (?s: \\. [^"\\]*+ )*+ " )
    (?<table> \[ (?: \s* \g<value> (?: \s* , \s* \g<value> )*+ )? \s* ] )
    (?<object> { 
        (?: \s* \g<key> \s* : \s* \g<value> 
            (?: \s* , \s* \g<key> \s* : \s* \g<value> )*+ 
        )? \s* }
    )
    (?<boolean> [Tt]rue | [Ff]alse )
    (?<number> (?: [0-9]+ (?: \. [0-9]* )? | \.[0-9]+ )
               (?: [Ee] -? [0-9]+ )? )

    (?<key> \g<string> (?<= [^"]" | \\"" ) )
    (?<value> \g<table> | \g<object> | \g<string>
            | \g<number> | \g<boolean> | null )
)
~x