json序列化一个以元组为关键字的字典

Rob*_*rto 54 python json

有没有办法在Python中序列化使用元组作为键的字典:

a={(1,2):'a'}
Run Code Online (Sandbox Code Playgroud)

简单地使用json.dumps(a),产生:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.6/json/__init__.py", line 230, in dumps
    return _default_encoder.encode(obj)
  File "/usr/lib/python2.6/json/encoder.py", line 367, in encode
    chunks = list(self.iterencode(o))
  File "/usr/lib/python2.6/json/encoder.py", line 309, in _iterencode
    for chunk in self._iterencode_dict(o, markers):
  File "/usr/lib/python2.6/json/encoder.py", line 268, in _iterencode_dict
    raise TypeError("key {0!r} is not a string".format(key))
TypeError: key (1, 2) is not a string
Run Code Online (Sandbox Code Playgroud)

Sin*_*ion 31

你不能把它序列化为json,json对于什么算作dict键而不是python有一个不那么灵活的想法.

您可以将映射转换为一系列键值对,如下所示:

>>> import json
>>> def remap_keys(mapping):
...     return [{'key':k, 'value': v} for k, v in mapping.iteritems()]
... 
>>> json.dumps(remap_keys({(1, 2): 'foo'}))
'[{"value": "foo", "key": [1, 2]}]'
Run Code Online (Sandbox Code Playgroud)

  • 您能否添加代码以在加载 JSON 后取消重新映射键?这将得到一个更完整的答案。 (2认同)
  • 请注意,Python 3 已重命名为 `dict.iteritems` -&gt; `dict.items` (2认同)

Ned*_*der 9

JSON仅支持字符串作为键.您需要选择一种将这些元组表示为字符串的方法.


Dhi*_*kur 7

你可以只使用str((1,2))键作为键,因为json只希望键作为字符串,但如果你使用它,你将不得不a[str((1,2))]用来获取值.


mar*_*ing 6

from json import load, dump
from ast import literal_eval

x={ (0,1):'la-la la', (0,2):'extricate' }

# save: convert each tuple key to a string before saving as json object
with open('/tmp/test', 'w') as f: dump({str(k):v for k, v in x.items()}, f)

# load in two stages:#
# (i) load json object
with open('/tmp/test', 'r') as f: obj = load(f)

# (ii) convert loaded keys from string back to tuple
d={literal_eval(k):v for k, v in obj.items()}
Run Code Online (Sandbox Code Playgroud)

参见:https : //stackoverflow.com/a/12337657/2455413


Nic*_*ews 6

这个解决方案:

  • 避免了安全风险eval()
  • 是短。
  • 可以像保存和加载功能一样复制粘贴。
  • 保留元组的结构作为键,以防您手动编辑 JSON。
  • 给元组表示增加丑陋\",这比这里的其他str()/eval()方法更糟糕。
  • 只能将元组作为嵌套字典第一级的键进行处理(截至撰写本文时,没有其他解决方案可以做得更好)
def json_dumps_tuple_keys(mapping):
    string_keys = {json.dumps(k): v for k, v in mapping.items()}
    return json.dumps(string_keys)

def json_loads_tuple_keys(string):
    mapping = json.loads(string)
    return {tuple(json.loads(k)): v for k, v in mapping.items()}

m = {(0,"a"): "first", (1, "b"): [9, 8, 7]}
print(m)      # {(0, 'a'): 'first', (1, 'b'): [9, 8, 7]}
s = json_dumps_tuple_keys(m)
print(s)      # {"[0, \"a\"]": "first", "[1, \"b\"]": [9, 8, 7]}
m2 = json_loads_tuple_keys(s)
print(m2)     # {(0, 'a'): 'first', (1, 'b'): [9, 8, 7]}
print(m==m2)  # True
Run Code Online (Sandbox Code Playgroud)