针对不同“深度”的不同json编码器

时间:2012-06-04 22:53:40

标签: python json

我想编写一个json编码器,它知道何时展开一个对象,或者将其保留为缩写形式。

我拥有的对象有许多属性,其中一些属性是其他对象的集合(而这些对象又具有自己的属性,可能是集合,无限制)。 json.dumps方法如果在所有对象中递归,则返回非常大的字符串。

是否可以设置“深度”,以便在该深度之后找到的任何对象不会进一步扩展?

2 个答案:

答案 0 :(得分:0)

首先,你应该弄清楚你是否真的在这里节省了硬盘。不要以百分比差异来考虑它,而是考虑运行程序的人的磁盘空间的美元成本。

其次,我想出了一个黑客的方法:

将文件夹/ Lib / json /复制到python安装之外的文件夹中。将文件夹命名为,例如jsondepth

转到encoder.py并进行3次更改(行号来自Python 2.7):

第411行,更改

def _iterencode(o, _current_indent_level):
    if isinstance(o, basestring):
        yield _encoder(o)

def _iterencode(o, _current_indent_level):
    if(_current_indent_level > SKIP_INDENT_LEVEL):
        yield 'null'
        return
    if isinstance(o, basestring):
        yield _encoder(o)

第335行,更改

def _iterencode_dict(dct, _current_indent_level):
    if not dct:
        yield '{}'

def _iterencode_dict(dct, _current_indent_level):
    if(_current_indent_level > SKIP_INDENT_LEVEL):
        yield 'null'
        return
    if not dct:
        yield '{}'

第282行,更改

def _iterencode_list(lst, _current_indent_level):
    if not lst:
        yield '[]'

def _iterencode_list(lst, _current_indent_level):
    if(_current_indent_level > SKIP_INDENT_LEVEL):
        yield 'null'
        return
    if not lst:
        yield '[]'

第5行,更改

try:
    from _json import encode_basestring_ascii as c_encode_basestring_ascii
except ImportError:
    c_encode_basestring_ascii = None
try:
    from _json import make_encoder as c_make_encoder
except ImportError:
    c_make_encoder = None

c_encode_basestring_ascii = None
c_make_encoder = None

位于文件顶部的某处(例如第13行)

SKIP_INDENT_LEVEL = 4 # or whatever recursion depth you want.

请注意,必须启用缩进,否则会完全崩溃。另请注意,我没有测试过这个。没有明示或暗示的保证:)

答案 1 :(得分:0)

我认为最简单的只是制作你的dict副本,根据需要编辑副本,然后使用JSON库对你的副本进行JSON编码。

使用这样的递归函数复制字典并在给定级别停止是一个非常简单的问题:

def is_dict(x):
    return hasattr(x, "has_key")

def dict_copy_n(d_to_copy, max_levels):
    assert max_levels >= 0
    d = {}
    for k, v in d_to_copy.items():
        if is_dict(v):
            if max_levels > 0:
                d[k] = dict_copy_n(v, max_levels - 1)
            else:
                # set key to None; or, delete the else: case to just ignore
                d[k] = None
        else:
            d[k] = v
    return d

以上代码会复制所有内容,直到max_levels向下计数为0,此时,任何值为dict的密钥都会在复制数据集中设置为None。您可以轻松编辑上述代码,将密钥设置为其他值,或者只是不复制该密钥。

因此,使用上面的函数制作原始文件的部分副本,然后对副本进行JSON编码。