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
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}]}
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}
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).
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.
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 ...)
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.