我想转储一些大的JSON文件,仅打印每个列表的前几个元素。我正在尝试编写自定义编码器:
class EllidingEncoder(json.JSONEncoder):
def encode(self, obj):
if isinstance(obj, list) and len(obj) > 6:
return "[{:}, …]".format(", ".join([self.encode(i) for i in obj[:6]]))
else:
# The problem....
return super(EllidingEncoder, self).encode(obj)
这类作品:
$ json.dumps([i for i in range(7)], cls=EllidingEncoder)
> '[0, 1, 2, 3, 4, 5, …]'
$ json.dumps([list([i for i in range(7)] for i in range(7)], cls=EllidingEncoder)
> '[[0, 1, 2, 3, 4, 5, …], [0, 1, 2, 3, 4, 5, …], [0, 1, 2, 3, 4, 5, …], [0, 1, 2, 3, 4, 5, …], [0, 1, 2, 3, 4, 5, …], [0, 1, 2, 3, 4, 5, …], …]'
但是一旦字典中包含列表,事情就会崩溃:
$ json.dumps({i:[i for i in range(7)] for i in range(7)}, cls=EllidingEncoder)
> '{"0": [0, 1, 2, 3, 4, 5, 6], "1": [0, 1, 2, 3, 4, 5, 6], "2": [0, 1, 2, 3, 4, 5, 6], "3": [0, 1, 2, 3, 4, 5, 6], "4": [0, 1, 2, 3, 4, 5, 6], "5": [0, 1, 2, 3, 4, 5, 6], "6": [0, 1, 2, 3, 4, 5, 6]}'
这很有意义,因为JSONEncoder.encode无法知道应该调用EllidingEncoder.encode。
我开始怀疑这样做根本无法做到。我的解决方法是显式覆盖dict的内容:
class EllidingEncoder(json.JSONEncoder):
def encode(self, obj):
if isinstance(obj, list) and len(obj) > 6:
return "[{:}, …]".format(", ".join([self.encode(i) for i in obj[:6]]))
elif isinstance(obj, dict):
return "{{{:}}}".format(", ".join(["{:} : {:}".format(k,self.encode(v)) for k,v in obj.items()]))
else:
return super(EllidingEncoder, self).encode(obj)
有什么想法吗?
编辑:当然,还需要显式处理包含6个以上元素的列表!
class EllidingEncoder(json.JSONEncoder):
def encode(self, obj):
if isinstance(obj, list):
if len(obj) > 6:
return "[{:}, …]".format(", ".join([self.encode(i) for i in obj[:6]]))
else:
return "[{:}]".format(", ".join([self.encode(i) for i in obj]))
elif isinstance(obj, dict):
return "{{{:}}}".format(", ".join(["{:} : {:}".format(k,self.encode(v)) for k,v in obj.items()]))
else:
return super(EllidingEncoder, self).encode(obj)