2012-02-01 51 views
5

打印使用json.dumps()整数作为十六进制字符串目前我使用下面的代码打印一个大的数据结构如何在Python

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

[八和六角形式不容许JSON(http://tools.ietf.org/html/rfc4627#section-2.4) – jfs 2012-02-01 19:10:21

+0

注:您的hexify _ *()函数可以松散的数据。如果你走这条路,你可以使用[类似的东西](http://ideone.com/G2DJG) – jfs 2012-02-01 21:48:06

+0

你能解释它是如何丢失数据的吗? – Plazgoth 2012-02-01 23:15:55

回答

2

一种可能的方法是有一个serialize函数,它会生成一个dictionar的副本y 动态并使用标准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模块的副本,并根据需要定制它。

干杯。

+0

你会如何使用列表工作? – Plazgoth 2012-02-01 19:41:45

+0

内存参数在我的情况下是无效的。所以我喜欢这种方法。我正在测试它,并试图找出如何使它适用于列表和列表清单。我的数据结构不是很大,但它很丑:) – Plazgoth 2012-02-01 20:13:36

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

注:这是不是特别“稳健”(失败嵌入在字符串的数字,漂浮等),但可能是足够你想要的东西(你也可以在这里增加正则表达式,这样它可以在更多的情况下工作)。为Python 2.7

+0

感谢这看起来很有希望,我会消化它,测试它并回复你。 – Plazgoth 2012-02-01 18:54:56

+0

所以这个工作,但它转换数字,即使当他们是像'x86_64'字符串的一部分变成'x0x54_0x40'我花了几分钟玩弄正则表达式来尝试修复,但放弃了:) – Plazgoth 2012-02-01 19:43:43

0

肮脏的黑客,我不会推荐使用它:

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

+0

我使用Python 2.6目前。但谢谢你的想法。 – Plazgoth 2012-02-01 18:54:19

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} 
+0

Yaml不是我正在使用的服务器上的Python安装的一部分,我现在不想在本地添加模块。但这看起来不错。 – Plazgoth 2012-02-01 20:07:35

+0

@Plazgoth:你将无法加载[十六进制数字与json整数](http://ideone.com/cInsT)。 – jfs 2012-02-01 20:11:10

+0

啊,我明白你的意见。我实际上不会将这个输出导入为json。这只是试图以可读的方式将数据结构打印到标准输出。谢谢,我应该在我的问题中说明这一点。 – Plazgoth 2012-02-01 20:30:17

0

你总是可以重新分析JSON,在那里你有过INT解析一些控制,使您可以覆盖INT再版:

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

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

+0

这工作正常,但它不保留数据中的订单是一个有序的字典。 – Plazgoth 2012-02-02 16:53:56