python - 如何截断字典中的数据以使生成的 JSON 不超过 n 个字节?

标签 python unicode json micro-optimization

我有一个 python 2.7 字典,例如 {u"eat": u"糖果", u"drink": u"café"},我需要使用 JSON 传输它。 JSON 字符串必须是常规 ASCII,并且必须少于 256 个字符。

到目前为止,我已经编写了以下代码:

import json

def payload_to_json(payload, max_size = 256):
    while True:
        json_string = json.dumps(payload, separators = (',', ':'))
        if len(json_string) <= max_size:
            return json_string
        max_length, found_key = 0, None
        for key, value in payload.iteritems():
            length = len(value)
            if length > max_length:
                max_length = length
                found_key = key
        if max_length == 0:
            return "" # just in case max_size is really low
        payload[found_key] = payload[found_key][:-1] # remove one char

它按预期工作:

>>> payload = {u"eat": u"糖果", u"drink": u"café"}
>>> print payload_to_json(payload)
{"drink":"caf\u00e9","eat":"\u7cd6\u679c"}
>>> print payload_to_json(payload, max_size=41)
{"drink":"caf","eat":"\u7cd6\u679c"}
>>> print payload_to_json(payload, max_size=35)
{"drink":"ca","eat":"\u7cd6\u679c"}
>>> print payload_to_json(payload, max_size=34)
{"drink":"c","eat":"\u7cd6\u679c"}
>>> print payload_to_json(payload, max_size=30)
{"drink":"c","eat":"\u7cd6"}
>>> print payload_to_json(payload, max_size=21)
{"drink":"","eat":""}
>>> print payload_to_json(payload, max_size=20)

我觉得应该有办法优化这个!我真的一次剥离一个字符,感觉很不对。

我的问题非常接近 this one ,除了我使用 python 2.7,只要源字符串包含非 ASCII unicode 字符,json 编码器就会生成相当长的 JSON 字符串。

另外,我很确定这会破坏 UTF-16 代理对...

最佳答案

如果你试图让它更快(你不应该这样做,除非你知道这是你程序中的一个热点,并且有实际的性能成本),你可以先猜测要剥离的字符数,然后处理剩菜。

首先,如果你需要剥离 52 个字符,并且有 10 个键,你需要从 2 个键中每个剥离 6 个字符,从其他 8 个键中每个剥离 5 个字符,对吗?当然,除了您可能试图从只有 4 个字符长的内容中删除 6 个字符,这意味着您最终仍会超出限制 2 个字符。但是您可以跟踪这些剩菜并在完成后处理它们。不太可能有足够的剩菜来让另一次通过“快速”版本值得做,所以你最好使用“慢速”版本。

def payload_to_json(payload, max_size = 256):
    json_string = json.dumps(payload, separators = (',', ':'))
    chars_to_strip = len(json_string) - max_size
    if chars_to_strip <= 0:
        return json_string
    key_count = len(payload)
    chars_per_key, extras = divmod(chars_to_strip, key_count)
    leftover = 0
    for i, key in enumerate(payload):
        to_strip = chars_per_key + (i < extras)
        orig_len = len(payload[key])
        if orig_len < to_strip:
            payload[key] = ''
            leftover += to_strip - orig_len
        else:
            payload[key] = payload[key][:-to_strip]
    if leftover:
        return slow_payload_to_json(payload, max_size)
    else:
        return json.dumps(payload, separators = (',', ':'))

我不确定这实际上在您的用例中加快速度。对于非常小的物体和最大尺寸,如果它真的减慢了速度,我不会感到惊讶。但是对于超过最大尺寸的巨大物体,它可能会有很大帮助。

关于python - 如何截断字典中的数据以使生成的 JSON 不超过 n 个字节?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15168974/

相关文章:

python - HTML 代码在模板中显示为文本

python - scipy.signal.fftconvolve 没有给出所需的结果

python - 从本地 gearman 客户端调用远程 gearman 工作人员?

python - python 中的 32 位 unicode

javascript - 使用jquery从Json获取数据

python - 不使用切片的 Numpy 索引

pdf - Kendo Grid 波斯语/阿拉伯语 PDF 导出问题

java - 使用 XMLStreamReader 转义字符

android - 检查来自android中服务器的响应

java - 使用 Gson 解析 JSON 映射/字典?