如何在Python中使用json.dumps()将整数打印为十六进制字符串
目前我正在使用以下代码来打印一个很大的数据结构。
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 模块的副本,并根据需要进行调整。
祝好。