消除长列表的JSONEncoder

时间:2019-02-25 10:58:33

标签: python json superclass

我想转储一些大的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)

0 个答案:

没有答案