从文本文件中检索JSON对象(使用Python)

2024-04-18 14:10:59 发布

您现在位置:Python中文网/ 问答频道 /正文

我有数千个包含多个JSON对象的文本文件,但不幸的是,这些对象之间没有分隔符。对象被存储为字典,它们的一些字段本身就是对象。每个对象可能有一个可变数量的嵌套对象。具体地说,一个对象可能是这样的:

{field1: {}, field2: "some value", field3: {}, ...} 

在一个文本文件中,数百个这样的对象在没有分隔符的情况下连接在一起。这意味着我既不能使用json.load(),也不能使用json.loads()

关于我如何解决这个问题的任何建议。是否有已知的解析器来执行此操作?


Tags: 对象json数量字典value情况loadsome
3条回答

这将从字符串中解码JSON对象的“列表”:

from json import JSONDecoder

def loads_invalid_obj_list(s):
    decoder = JSONDecoder()
    s_len = len(s)

    objs = []
    end = 0
    while end != s_len:
        obj, end = decoder.raw_decode(s, idx=end)
        objs.append(obj)

    return objs

这里的好处是您可以很好地使用解析器。因此它总是告诉你它在哪里发现了错误。

示例

>>> loads_invalid_obj_list('{}{}')
[{}, {}]

>>> loads_invalid_obj_list('{}{\n}{')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "decode.py", line 9, in loads_invalid_obj_list
    obj, end = decoder.raw_decode(s, idx=end)
  File     "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/decoder.py", line 376, in raw_decode
    obj, end = self.scan_once(s, idx)
ValueError: Expecting object: line 2 column 2 (char 5)

清洁溶液(稍后添加)

import json
import re

#shameless copy paste from json/decoder.py
FLAGS = re.VERBOSE | re.MULTILINE | re.DOTALL
WHITESPACE = re.compile(r'[ \t\n\r]*', FLAGS)

class ConcatJSONDecoder(json.JSONDecoder):
    def decode(self, s, _w=WHITESPACE.match):
        s_len = len(s)

        objs = []
        end = 0
        while end != s_len:
            obj, end = self.raw_decode(s, idx=_w(s, end).end())
            end = _w(s, end).end()
            objs.append(obj)
        return objs

示例

>>> print json.loads('{}', cls=ConcatJSONDecoder)
[{}]

>>> print json.load(open('file'), cls=ConcatJSONDecoder)
[{}]

>>> print json.loads('{}{} {', cls=ConcatJSONDecoder)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", line 339, in loads
    return cls(encoding=encoding, **kw).decode(s)
  File "decode.py", line 15, in decode
    obj, end = self.raw_decode(s, idx=_w(s, end).end())
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/decoder.py", line 376, in raw_decode
    obj, end = self.scan_once(s, idx)
ValueError: Expecting object: line 1 column 5 (char 5)

塞巴斯蒂安·布拉斯克(Sebastian Blask)的想法是正确的,但没有理由使用regex进行如此简单的更改。

objs = json.loads("[%s]"%(open('your_file.name').read().replace('}{', '},{')))

或者,更清楚地说

raw_objs_string = open('your_file.name').read() #read in raw data
raw_objs_string = raw_objs_string.replace('}{', '},{') #insert a comma between each object
objs_string = '[%s]'%(raw_objs_string) #wrap in a list, to make valid json
objs = json.loads(objs_string) #parse json

这样怎么样:

import re
import json

jsonstr = open('test.json').read()

p = re.compile( '}\s*{' )
jsonstr = p.sub( '}\n{', jsonstr )

jsonarr = jsonstr.split( '\n' )

for jsonstr in jsonarr:
   jsonobj = json.loads( jsonstr )
   print json.dumps( jsonobj )

相关问题 更多 >