正则表达式匹配嵌套的json对象

时间:2013-07-22 11:28:50

标签: java regex

我正在实现某种解析器,我需要找到并反序列化嵌入到其他半结构化数据中的json对象 。我使用了regexp:

\\{\\s*title.*?\\}

找到对象

{title:'Title'}

但它不适用于嵌套对象,因为表达式仅匹配第一个找到的右括号。对于

{title:'Title',{data:'Data'}}

匹配

{title:'Title',{data:'Data'}

因此字符串对于反序列化变得无效。 我知道有一个贪婪的业务,但我不熟悉正则表达式。你可以帮我扩展表达式以消耗所有可用的结束花括号。

更新

要明确的是,这是尝试从带有嵌入式JSON的HTML + JS等半结构化数据中提取JSON数据。我正在使用GSon JAVA lib来实际解析提取的JSON。

4 个答案:

答案 0 :(得分:4)

正如其他人所建议的那样,一个成熟的JSON解析器可能就是这样。如果要匹配上面的简单示例中的键值对,可以使用:

(?<=\{)\s*[^{]*?(?=[\},])

输入字符串

{title:'Title',  {data:'Data', {foo: 'Bar'}}}

匹配:

 1. title:'Title'
 2. data:'Data'
 3. foo: 'Bar'

答案 1 :(得分:2)

感谢@Sanjay T. Sharma指出我“支持匹配”,因为我最终对贪婪的表达有了一些了解,也感谢其他人最初说我不该做的事情。 幸运的是,结果表明使用贪婪的表达变体

是可以的
\\{\s*title.*\\}

因为右括号之间没有非JSON数据。

答案 2 :(得分:2)

此递归Perl / PCRE正则表达式应该能够匹配任何有效的JSON或JSON5对象,包括嵌套对象和边缘情况,例如JSON字符串或JSON5注释中的花括号:

/(\{(?:(?>[^{}"'\/]+)|(?>"(?:(?>[^\\"]+)|\\.)*")|(?>'(?:(?>[^\\']+)|\\.)*')|(?>\/\/.*\n)|(?>\/\*.*?\*\/)|(?-1))*\})/

当然,这有点难以理解,因此您可能更喜欢带注释的版本:

m{
  (                               # Begin capture group (matching a JSON object).
    \{                              # Match opening brace for JSON object.
    (?:                             # Begin non-capturing group to contain alternations.
      (?>[^{}"'\/]+)                  # Match a non-empty string which contains no braces, quotes or slashes, without backtracking.
    |                               # Alternation; next alternative follows.
      (?>"(?:(?>[^\\"]+)|\\.)*")      # Match a double-quoted JSON string, without backtracking.
    |                               # Alternation; next alternative follows.
      (?>'(?:(?>[^\\']+)|\\.)*')      # Match a single-quoted JSON5 string, without backtracking.
    |                               # Alternation; next alternative follows.
      (?>\/\/.*\n)                    # Match a single-line JSON5 comment, without backtracking.
    |                               # Alternation; next alternative follows.
      (?>\/\*.*?\*\/)                 # Match a multi-line JSON5 comment, without backtracking.
    |                               # Alternation; next alternative follows.
      (?-1)                           # Recurse to most recent capture group, to match a nested JSON object.
    )*                              # End of non-capturing group; match zero or more repetitions of this group.
    \}                              # Match closing brace for JSON object.
  )                               # End of capture group (matching a JSON object).
}x

答案 3 :(得分:0)

这绝对是可怕的,我无法相信我实际上是在为这个解决方案添加我的名字,但是你找不到Javascript块中的第一个{字符并尝试解析剩余的字符通过适当的JSON解析库?如果它有效,你就得到了一个匹配。如果没有,请继续阅读直至下一个{字符并重新开始。

那里有一些问题,但它们可能可以解决:

  • 您需要能够识别Javascript块。大多数语言都有HTML到DOM库(我是Java的Cyberneko的忠实粉丝),这使得我们可以轻松地关注<script>...</script>块。
  • 您的JSON解析库需要在发现错误时立即停止使用流中的字符,并且当它发生时它不需要关闭流。

一旦找到第一个{,就会有一个改进,就是找一个匹配的}(一个简单的计数器,只要你找到{并且递减就会增加当你发现}应该做的伎俩)。尝试将生成的字符串解析为JSON。迭代直到它工作或你已经用完了可能的块。

这是丑陋的,hackish,永远不应该成为生产代码。我得到的印象是,你只需要批量工作,这就是为什么我甚至建议它。