我有一个非标准的“JSON”文件要解析。每个项目都以分号分隔而不是逗号分隔。我不能简单地用 ; 替换 , ,因为可能有一些包含 ; 的值,例如。 “你好,世界”。我怎样才能将它解析成与 JSON 通常解析它相同的结构?

{
  "client" : "someone";
  "server" : ["s1"; "s2"];
  "timestamp" : 1000000;
  "content" : "hello; world";
  ...
}

最佳答案

使用 Python tokenize module 将文本流转换为带有逗号而不是分号的文本流。 Python 标记器也很乐意处理 JSON 输入,甚至包括分号。分词器将字符串作为整个标记呈现,“原始”分号在流中作为单个 token.OP 标记供您替换:

import tokenize
import json

corrected = []

with open('semi.json', 'r') as semi:
    for token in tokenize.generate_tokens(semi.readline):
        if token[0] == tokenize.OP and token[1] == ';':
            corrected.append(',')
        else:
            corrected.append(token[1])

data = json.loads(''.join(corrected))

这假设一旦您用逗号替换分号,格式就会变成有效的 JSON;例如在关闭 ]} 之前不允许尾随逗号,尽管您甚至可以跟踪添加的最后一个逗号,如果下一个非换行符是右大括号,则可以再次删除它。

演示:
>>> import tokenize
>>> import json
>>> open('semi.json', 'w').write('''\
... {
...   "client" : "someone";
...   "server" : ["s1"; "s2"];
...   "timestamp" : 1000000;
...   "content" : "hello; world"
... }
... ''')
>>> corrected = []
>>> with open('semi.json', 'r') as semi:
...     for token in tokenize.generate_tokens(semi.readline):
...         if token[0] == tokenize.OP and token[1] == ';':
...             corrected.append(',')
...         else:
...             corrected.append(token[1])
...
>>> print ''.join(corrected)
{
"client":"someone",
"server":["s1","s2"],
"timestamp":1000000,
"content":"hello; world"
}
>>> json.loads(''.join(corrected))
{u'content': u'hello; world', u'timestamp': 1000000, u'client': u'someone', u'server': [u's1', u's2']}

token 间空白被删除,但可以通过注意 tokenize.NL token 以及作为每个 token 一部分的 (lineno, start)(lineno, end) 位置元组来重新设置。由于 token 周围的空格对 JSON 解析器无关紧要,因此我没有为此烦恼。

关于python - 解析非标准分号分隔的 "JSON",我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38924902/

10-11 20:34
查看更多