我想编写一个 json 编码器,它知道何时扩展对象,或将其保留为缩写形式。
我拥有的对象有很多属性,其中一些是其他对象的集合(这些对象又具有自己的属性,可能是集合,无穷无尽)。json.dumps
如果递归遍历所有对象,该方法可能会返回非常大的字符串。
是否可以设置“深度”,以便在该深度之后找到的任何对象都不会进一步扩展?
首先,你应该弄清楚你是否真的在这里节省了硬盘。不要考虑百分比差异,而是考虑运行程序的人的磁盘空间美元成本。
其次,我想出了一个 hacky 方法:
将文件夹 /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.
请注意,必须启用缩进,否则这将完全崩溃。另请注意,我没有对此进行测试。没有明示或暗示的保证:)
我认为最简单的方法就是复制您的 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,此时任何值为 a 的键都在复制字典中dict
简单地设置为。None
您可以轻松地编辑上述代码以将密钥设置为其他值,或者干脆不复制该密钥。
因此,使用上述函数制作原始的部分副本,然后对副本进行 JSON 编码。