如何在Python中使用json.dumps()将整数打印为十六进制字符串

7 投票
7 回答
10603 浏览
提问于 2025-04-17 12:08

目前我正在使用以下代码来打印一个很大的数据结构。

print(json.dumps(data, indent=4))

我想把打印出来的所有整数都显示成十六进制,而不是十进制。这样做可以吗?看起来没有办法去改变现有的整数编码方式。你只能为那些 JSONEncoder 类没有处理的类型提供默认值,但不能改变它是如何编码整数的。

我发现如果在命令行下运行,可以通过 sys.displayhook 来改变默认的整数打印方式,但我现在不是在命令行下。

为了说明,这个数据结构包含了字典、列表、字符串、整数等等,所以我选择了 json.dumps()。我能想到的另一种方法就是自己解析数据,但那样的话我就得重写 json 模块了。

更新: 所以我最终实现了一个序列化函数,它会打印出原始数据结构的副本,并把所有整数类型转换成十六进制字符串:

def odprint(self, hexify=False):
    """pretty print the ordered dictionary"""
    def hexify_list(data):
        _data = []
        for i,v in enumerate(data):
            if isinstance(v, (int,long)):
                _data.insert(i,hex(v))
            elif isinstance(v,list):
                _data.insert(i, hexify_list(v))
            else:
                _data.insert(i, val)
        return _data

    def hexify_dict(data):
        _data = odict()
        for k,v in data.items():
            if isinstance(v, (dict,odict)):
                _data[k] = hexify_dict(v)
            elif isinstance(v, (int, long)):
                _data[k] = hex(v)
            elif isinstance(v,list):
                _data[k] = hexify_list(v)
            else:
                _data[k] = v
        return _data

    if hexify:
        print(json.dumps(hexify_dict(self), indent=4))
    else:
        print(json.dumps(self, indent=4))

谢谢大家的帮助。我意识到我把标准字典变成了有序字典,但这只是为了打印,所以对我来说没问题。

7 个回答

1

你可以重新解析一下json,这样你就可以控制整数的解析方式,从而可以自定义整数的表示:

class hexint(int):
   def __repr__(self):
     return "0x%x" % self

json.loads(json.dumps(data), parse_int=hexint)

而且使用data,就像Gerrat的回答中提到的,输出结果是:

{u'test': 0x21, u'this': 0x63, u'something bigger': [0x1, 0x2, 0x3, {u'a': 0x2c}]}
2

JSON 中,不支持八进制和十六进制格式。

你可以选择使用 YAML 来代替。

>>> import json, yaml
>>> class hexint(int):
...     def __str__(self):
...         return hex(self)
...
>>> json.dumps({"a": hexint(255)})
'{"a": 0xff}'
>>> yaml.load(_)
{'a': 255}

或者可以不对整数进行包装:

import yaml

def hexint_presenter(dumper, data):
    return dumper.represent_int(hex(data))
yaml.add_representer(int, hexint_presenter)

print yaml.dump({"a": 255}), # -> {a: 0xff}
assert yaml.load('{a: 0xff}') == {"a": 255}
2

一种可能的方法是创建一个叫做 serialize 的函数,这个函数可以实时生成你字典的一个副本,并使用标准的 json 模块将其转换成字符串。下面是一个初步的实现示例:

import json

def serialize(data):
    _data = {}
    for k, v in data.items():
        if isinstance(v, int):
            _data[k] = hex(v)
        else:
            _data[k] = v
    return json.dumps(_data, indent=4)


if __name__ == "__main__":
    data = {"a":1, "b":2.0, "c":3}
    print serialize(data)

输出结果:

{
    "a": "0x1", 
    "c": "0x3", 
    "b": 2.0
}

请注意,这个初步的实现不支持列表,但这个问题很容易解决。

有些人可能会说这种方法占用内存,因为它会创建原始数据的一个副本。确实可能是这样,但如果你的数据结构这么大,或许你应该考虑 (a) 不使用 JSON,或者 (b) 在你的工作目录中创建一个 JSON 模块的副本,并根据需要进行调整。

祝好。

撰写回答