How to print integers as hex strings using json.dumps() in Python

前端 未结 6 1966
没有蜡笔的小新
没有蜡笔的小新 2021-01-05 17:18

Currently I am using the following code to print a large data structure

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

I would like to see all the integ

相关标签:
6条回答
  • 2021-01-05 17:58

    You could always reparse the json, where you do have some control over int parsing, so that you can override int repr:

    class hexint(int):
       def __repr__(self):
         return "0x%x" % self
    
    json.loads(json.dumps(data), parse_int=hexint)
    

    And using the data as in Gerrat's answer, the output is:

    {u'test': 0x21, u'this': 0x63, u'something bigger': [0x1, 0x2, 0x3, {u'a': 0x2c}]}
    
    0 讨论(0)
  • 2021-01-05 17:59

    Octal and hexadecimal formats are not supported in JSON.

    You could use YAML instead.

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

    Or without wrapping integers:

    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}
    
    0 讨论(0)
  • 2021-01-05 18:03

    You can't override the existing encoder for integers...but there might be another way to get what you want. What about something like this:

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

    Results in:

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

    Note: This isn't especially "robust" (fails on numbers embedded in strings, floats, etc.), but might be good enough for what you want (You could also enhance the regex here so it would work in a few more cases).

    0 讨论(0)
  • 2021-01-05 18:08

    One-liner

    If you don't mind your hex strings quoted, use this one-liner:

    print(json.dumps(eval(str(json.loads(json.dumps(data), parse_int=lambda i:hex(int(i))))), indent=4))
    

    Output (using Gerrat's data again):

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

    This is a better answer than my previous post as I've dealt with getting a pretty-printed result.

    0 讨论(0)
  • 2021-01-05 18:18

    Dirty hack for Python 2.7, I wouldn't recomend to use it:

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

    Output:

    {
        "a": [
            0x1,
            0x2,
            0x3
        ],
        "c": 0x100000000000000000000L,
        "b": 0x4
    }
    

    On Python 3 __builtin__ module is now builtins, but I can't test it (ideone.com fails with ImportError: libz.so.1 ...)

    0 讨论(0)
  • 2021-01-05 18:19

    A possible approach is to have a serialize function, which produces a copy of your dictionary on the fly and uses the standard json module to dump the string. A preliminary implementation looks like:

    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)
    

    output:

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

    Notice that this preliminary implementation does not work with lists, but this is easily changed.

    Some may claim that the approach is memory-intensive because it creates a copy of the original data. This may be the case, but if your data structure is that big, then maybe you should (a) not be using JSON, or (b) create a copy of the JSON module in your working directory and tailor it to your needs.

    Cheers.

    0 讨论(0)
提交回复
热议问题