Skip to main content
 首页 » 编程设计

python之解析非标准分号分隔 "JSON"

2025年05月04日15lovecherry

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

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

请您参考如下方法:

使用 Python tokenize module将文本流转换为带有逗号而不是分号的文本流。 Python 分词器也很乐意处理 JSON 输入,甚至包括分号。 tokenizer 将字符串呈现为整个标记,并且“原始”分号在流中作为单个 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 和 (lineno, start) 和 来恢复(lineno, end) 定位作为每个标记一部分的元组。由于标记周围的空格对 JSON 解析器无关紧要,因此我没有为此烦恼。