从字符串中解析有效的JSON对象或数组

时间:2016-01-23 05:22:39

标签: python regex python-3.x

我有一个字符串,可以是以下两种形式之一:

name multi word description {...}

name multi word description [...]

其中{...}[...]是任何有效的JSON。我有兴趣解析字符串的JSON部分,但我不确定最好的方法(特别是因为我不知道字符串中的哪两种形式)。这是我目前的方法:

import json

string = 'bob1: The ceo of the company {"salary": 100000}' 
o_ind = string.find('{')
a_ind = string.find('[')

if o_ind == -1 and a_ind == -1:
    print("Could not find JSON")
    exit(0)

index = min(o_ind, a_ind)
if index == -1:
    index = max(o_ind, a_ind)

json = json.loads(string[index:])
print(json)

它有效,但我无法帮助,但感觉可以做得更好。我想也许正则表达式,但我遇到了匹配子对象和数组的问题,而不是最外面的json对象或数组。有什么建议吗?

2 个答案:

答案 0 :(得分:5)

您可以通过检查{[的存在来找到JSON的开头,然后将字符串末尾的所有内容保存到捕获组中:

>>> import re
>>> string1 = 'bob1: The ceo of the company {"salary": 100000}'
>>> string2 = 'bob1: The ceo of the company ["10001", "10002"]'
>>> 
>>> re.search(r"\s([{\[].*?[}\]])$", string1).group(1)
'{"salary": 100000}'
>>> re.search(r"\s([{\[].*?[}\]])$", string2).group(1)
'["10001", "10002"]'

此处\s([{\[].*?[}\]])$分解为:

  • \s - 单个空格字符
  • 括号为capturing group
  • [{\[]会匹配单个{[(后者需要使用反斜杠进行转义)
  • .*?是任意次数的 non-greedy 匹配
  • [}\]]会匹配单个}](后者需要使用反斜杠进行转义)
  • $表示字符串的结尾

或者,您可以使用re.split()将字符串拆分为空格,然后是{[(前面是肯定的)并获取最后一项。它适用于您提供的样本输入,但不确定这是否可靠:

>>> re.split(r"\s(?=[{\[])", string1)[-1]
'{"salary": 100000}'
>>> re.split(r"\s(?=[{\[])", string2)[-1]
'["10001", "10002"]'

答案 1 :(得分:3)

您可以在正则表达式中使用简单的|来匹配所需的子字符串:

import re
import json

def json_from_s(s):
    match = re.findall(r"{.+[:,].+}|\[.+[,:].+\]", s)
    return json.loads(match[0]) if match else None

还有一些测试:

print json_from_s('bob1: The ceo of the company {"salary": 100000}')
print json_from_s('bob1: The ceo of the company ["salary", 100000]')
print json_from_s('bob1')
print json_from_s('{1:}')
print json_from_s('[,1]')

输出:

{u'salary': 100000}
[u'salary', 100000]
None
None
None