我有一个文本文档,其中有几千个jsons字符串,格式为:"{...}{...}{...}"
。这不是一个有效的json,而是每个{...}
。
我目前使用以下正则表达式来分割它们:
fp = open('my_file.txt', 'r')
raw_dataset = (re.sub('}{', '}\n{', fp.read())).split('\n')
这基本上打破了大括号关闭和其他打开(}{ -> }\n{
)的每一行,因此我可以将它们分成不同的行。
问题在于,很少有tags
属性写为"{tagName1}{tagName2}"
,这会破坏我的正则表达式。
一个例子是:
'{"name":\"Bob Dylan\", "tags":"{Artist}{Singer}"}{"name": "Michael Jackson"}'
被解析为
'{"name":"Bob Dylan", "tags":"{Artist}'
'{Singer}"}'
'{"name": "Michael Jackson"}'
而不是
'{"name":"Bob Dylan", "tags":"{Artist}{Singer}"}'
'{"name": "Michael Jackson"}'
为进一步的json解析实现这个的正确方法是什么?
答案 0 :(得分:4)
使用json.JSONDecoder的raw_decode方法
>>> import json
>>> d = json.JSONDecoder()
>>> x='{"name":\"Bob Dylan\", "tags":"{Artist}{Singer}"}{"name": "Michael Jackson"}'
>>> d.raw_decode(x)
({'tags': '{Artist}{Singer}', 'name': 'Bob Dylan'}, 47)
>>> x=x[47:]
>>> d.raw_decode(x)
({'name': 'Michael Jackson'}, 27)
raw_decode返回一个2元组,第一个元素是解码的JSON,第二个元素是JSON结束后下一个字节的字符串中的偏移量。
循环直到结束或遇到无效的JSON元素:
>>> while True:
... try:
... j,n = d.raw_decode(x)
... except ValueError:
... break
... print(j)
... x=x[n:]
...
{'name': 'Bob Dylan', 'tags': '{Artist}{Singer}'}
{'name': 'Michael Jackson'}
当循环中断时,检查x将显示它是否已处理整个字符串或遇到JSON语法错误。
使用一个非常长的短元素文件,你可以将一个块读入一个缓冲区并应用上面的循环,在循环中断后将剩下的任何内容与下一个块连接起来。
答案 1 :(得分:2)
您可以使用jq
命令行实用程序将输入传输到json。我们假设您有以下输入:
input.txt中:
{"name":"Bob Dylan", "tags":"{Artist}{Singer}"}{"name": "Michael Jackson"}
您可以使用jq -s
,它会从输入中使用多个json文档并将它们传输到单个输出数组中:
jq -s . input.txt
给你:
[
{
"name": "Bob Dylan",
"tags": "{Artist}{Singer}"
},
{
"name": "Michael Jackson"
}
]
我刚刚意识到libjq
有python绑定。意思你
不需要使用命令行,您可以直接在python中使用jq
。
https://github.com/mwilliamson/jq.py
但是,到目前为止我还没有尝试过。让我试一试:) ...
更新:上面的库很不错,但到目前为止它还不支持slurp模式。
答案 2 :(得分:1)
你需要做一个解析器...我不认为正则表达式可以帮助你
data = ""
curlies = []
def get_dicts(file_text):
for letter in file_text:
data += letter
if letter == "{":
curlies.append(letter)
elif letter == "}":
curlies.pop() # remove last
if not curlies:
yield json.loads(data)
data = ""
请注意,这实际上并没有解决{name:"bob"}
无效的问题json ... {"name":"bob"}
如果你在字符串里面有奇怪的不平衡括号,这也会破坏,即{"name":"{{}}}"}
会打破这个
基于你的例子,你的json真的被打破了你最好的选择可能就是手工编辑并修复生成它的代码......如果这不可行,你可能需要使用pylex编写一个更复杂的解析器或其他一些语法库(有效地编写自己的语言解析器)