我有成千上万个包含多个JSON对象的文本文件,但是不幸的是,这些对象之间没有分隔符。对象存储为字典,它们的某些字段本身就是对象。每个对象可能具有可变数量的嵌套对象。具体来说,一个对象可能看起来像这样:
{field1: {}, field2: "some value", field3: {}, ...}
并在文本文件中串联了数百个这样的对象而没有分隔符。这意味着我既不能使用json.load()也不可以json.loads()。
json.load()
json.loads()
关于如何解决此问题的任何建议。是否有已知的解析器可以执行此操作?
这将从字符串中解码您的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)