目前我使用以下代码打印大型数据结构
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))
感谢您的帮助。我意识到我最终会从一个标准的字典中做出一个冒险,但它只是用于印刷,所以我的需要很好。
答案 0 :(得分: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模块的副本并根据您的需要进行定制。 / p>
干杯。
答案 1 :(得分: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 :(得分:1)
你不能覆盖整数的现有编码器......但可能有另一种方法来获得你想要的东西。这样的事情怎么样:
import json
import re
data = {'test': 33, 'this': 99, 'something bigger':[1,2,3, {'a':44}]}
s = json.dumps(data, indent=4)
print(re.sub('(\d+)', lambda i: hex(int(i.group(0))),s))
结果:
{
"test": 0x21,
"this": 0x63,
"something bigger": [
0x1,
0x2,
0x3,
{
"a": 0x2c
}
]
}
注意:这不是特别“强大”(嵌入在字符串,浮点数等中的数字失败),但可能足以满足您的需要(您还可以在此处增强正则表达式,以便它可以在几个案例)。
答案 3 :(得分:0)
Python 2.7的肮脏黑客,我不会建议使用它:
import __builtin__
_orig_str = __builtin__.str
def my_str(obj):
if isinstance(obj, (int, long)):
return hex(obj)
return _orig_str(obj)
__builtin__.str = my_str
import json
data = {'a': [1,2,3], 'b': 4, 'c': 16**20}
print(json.dumps(data, indent=4))
输出:
{
"a": [
0x1,
0x2,
0x3
],
"c": 0x100000000000000000000L,
"b": 0x4
}
在Python 3上__builtin__
模块现在是builtins
,但我无法测试它(ideone.com失败,导入错误:libz.so.1 ...)
答案 4 :(得分:0)
你总是可以重新解析json,你可以对int解析有一些控制权,这样你就可以覆盖int repr:
class hexint(int):
def __repr__(self):
return "0x%x" % self
json.loads(json.dumps(data), parse_int=hexint)
在Gerrat的答案中使用data
,输出为:
{u'test': 0x21, u'this': 0x63, u'something bigger': [0x1, 0x2, 0x3, {u'a': 0x2c}]}
答案 5 :(得分:0)
<强>一衬垫强>
如果你不介意引用你的六角形弦,请使用这个单行:
print(json.dumps(eval(str(json.loads(json.dumps(data), parse_int=lambda i:hex(int(i))))), indent=4))
输出(再次使用Gerrat的data
):
{
"test": "0x21",
"this": "0x63",
"something bigger": [
"0x1",
"0x2",
"0x3",
{
"a": "0x2c"
}
]
}
这是一个比我之前的帖子更好的答案,因为我已经处理了一个漂亮的印刷结果。