【问题标题】:How to find all dictionaries from a long string in python如何从python中的长字符串中查找所有字典
【发布时间】:2015-12-11 23:36:23
【问题描述】:

我正在尝试从一个长字符串中检索所有类似 JSON 的字典。 例如,

{"uri": "something"} is referencing {"link": "www.aurl.com"}

我想得到{"uri": "something"}{"link": "www.aurl.com"} 作为结果。有没有办法通过python中的正则表达式来做到这一点?

【问题讨论】:

  • re.findall(r'\{[^}]*\}', s)
  • @AvinashRaj:这种方法的缺陷是它无法处理嵌套对象。如果字符串是{"uri": {"domain": "example.com", "protocol": "https"}, "foo": "bar"} is referencing {"link": "www.aurl.com"},您的第一次捕获将省略, "foo": "bar"},从而导致无法解析的部分JSON。

标签: python json string parsing


【解决方案1】:

可能“最好”的方法是让真正的 JSON 解码器完成这项工作,而不是使用可怕的正则表达式。找到所有打开的大括号作为“可能的对象起点”,然后尝试使用JSONDecoderraw_decode 方法解析它们(该方法返回解析的对象和成功时消耗的字符数,从而可以有效地跳过成功解析的对象) .例如:

import json

def get_all_json(teststr):
    decoder = json.JSONDecoder()
    # Find first possible JSON object start point
    sliceat = teststr.find('{')
    while sliceat != -1:
        # Slice off the non-object prefix
        teststr = teststr[sliceat:]
        try:
            # See if we can parse it as a JSON object
            obj, consumed = decoder.raw_decode(teststr)
        except Exception:
            # If we couldn't, find the next open brace to try again
            sliceat = teststr.find('{', 1)
        else:
            # If we could, yield the parsed object and skip the text it was parsed from
            yield obj
            sliceat = consumed

这是一个生成器函数,因此您可以一个一个地迭代对象,例如for obj in get_all_json(mystr): 或者如果您需要它们一次全部用于索引、多次迭代等,all_objs = list(get_all_json(mystr))

【讨论】:

  • 根据您的数据,您可能需要调整解码器配置。例如,严格的 JSON 禁止控制字符,例如选项卡,换行符等,在字符串中,但有时真正的 JSON 有它们。将strict=False 传递给JSONDecoder 构造函数将允许解析该形式的字符串。还提供了更强大的自定义功能,请参阅the JSONDecoder docs
  • 如果您只想要字符串,而不是解码字典,您可以将yield obj 更改为yield teststr[:consumed]。虽然这使得 obj 一代成为“浪费”,但让真正的 JSON 解析器来完成这项工作仍然要好得多,而不是自己滚动,总是用正则表达式替换不好。
  • 感谢ShadowRanger 的详细解释。但是,我正在解析的字符串已知没有任何嵌套的 JSON。我将首先尝试 Avinash 的方法,但一定会牢记您的解决方案。 :)
  • 请不要。不必要地重新发明解析器会导致严重的痛苦。 JSON is not a regular language;尽管 Python 的正则表达式方言可以处理的不仅仅是一个真正的正则表达式引擎,但要让它 100% 正确仍然几乎是不可能的。 Like HTML, JSON cannot be parsed with regular expressions。失败示例:{"uri": "http://example.com/?res_id={3F2504E0-4F89-41D3-9A0C-0305E82C3301}"} 即使没有嵌套的 JSON 对象也会失败,因为字符串本身有一个右大括号。
猜你喜欢
  • 2019-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-03
  • 1970-01-01
相关资源
最近更新 更多