解析非标准分号“JSON”

时间:2016-08-12 19:05:17

标签: python json parsing

我有一个非标准的“JSON”文件要解析。每个项目以分号分隔,而不是以逗号分隔。我不能简单地将Resize()替换为;,因为可能有一些值包含,,例如。 “你好,世界”。我如何将其解析为JSON通常会解析它的结构?

;

3 个答案:

答案 0 :(得分:6)

使用Python tokenize module将文本流转换为逗号而不是分号。 Python tokenizer也很乐意处理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']}

删除了令牌间空格,但可以通过关注tokenize.NL令牌以及属于每个令牌的(lineno, start)(lineno, end)位置元组来重新设置。由于令牌周围的空白对JSON解析器无关紧要,我对此并不感到困扰。

答案 1 :(得分:0)

你可以做一些奇怪的事情并且(可能)正确。

因为JSON上的字符串不能包含\t之类的控制字符,所以您可以将每个;替换为\t,,这样如果您的JSON解析器能够加载非文件将正确解析该文件严格的JSON(例如Python')。

之后,您只需要将数据转换回JSON,这样就可以将所有这些\t,替换回;并使用普通的JSON解析器来最终加载正确的对象。

Python中的一些示例代码:

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

import json
dec = json.JSONDecoder(strict=False).decode(data.replace(';', '\t,'))
enc = json.dumps(dec)
out = json.loads(dec.replace('\\t,' ';'))

答案 2 :(得分:0)

使用简单的字符状态机,您可以将此文本转换回有效的JSON。我们需要处理的基本事情是确定当前的“状态”(我们是否转义字符,字符串,列表,字典等),并替换';'当','处于某种状态时。

我不知道这是否是写它的正确方法,可能有一种方法可以缩短它,但我没有足够的编程技巧来为此制作最佳版本。

我尽可能多地评论:

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

测试:

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

返回:

foreach (Control c in Controls)
{
    if (c is TextBox)
    {
        c.Text = "";