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

时间:2012-02-01 17:50:24

标签: python json integer hex

目前我使用以下代码打印大型数据结构

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))

感谢您的帮助。我意识到我最终会从一个标准的字典中做出一个冒险,但它只是用于印刷,所以我的需要很好。

6 个答案:

答案 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"
        }
    ]
}

这是一个比我之前的帖子更好的答案,因为我已经处理了一个漂亮的印刷结果。