Pavel Anossov 很好地回答了这个问题。要对元组等对象进行编码,代码可以工作。将元组作为 Python dict 键也很有用,并且上面的代码没有将元组作为 dict 键处理。要将元组作为键进行管理,可以使用表示元组是否为 dict 键的布尔标志,并且元组被包装在 json.dumps(...) 输出层中;在解码期间,json 通过递归处理。
解决方案可以允许传递元组与值的数据结构,从而更容易散列。Pythondef __hash__(self):
经常返回对象中项目元组的哈希值,有时使用不包含在类中的更简单的数据结构很有用。
- hint_tuples 可以有一个命名参数 dict_key - 元组的标志是一个字典键。Python dict 类型不能作为 dict 的键,最好使用 json.dumps(...) 将其转换为字符串,在解码期间应将其恢复为 dict,并且递归应注意将其转换为元组。
- 可选地
__tuple__
可以被混淆,以便如果有人将字符串编码__tuple__
为 dict 键的一部分,它可以通过编码器/解码器。
下面的代码是我想出的用于在 Python dict 键中编码元组的方法。包括几个基本测试作为__main__
演示解决方案的一部分。放弃编码输出的可读性以增加通过解决方案的案例数量。
# Pavel Anossov's solution hinted this:
import json
tuple_signifier = '__tuple__s_i_g_n_i_f_i_e_r__'
class StreamTuple(dict):
def __hash__(self):
return hash(str(self))
class MultiDimensionalArrayEncoder(json.JSONEncoder):
def encode(self, obj):
def hint_tuples(item, dict_key=False):
global tuple_signifier
ret_val = None
if isinstance(item, tuple):
if dict_key:
ret_val = json.dumps(dict(
[(
tuple_signifier,
json.dumps(hint_tuples(list(item))),
),],
))
else:
ret_val = dict(
[(
tuple_signifier,
json.dumps(hint_tuples(list(item))),
),],
)
elif isinstance(item, list):
ret_val = [hint_tuples(e) for e in item]
elif isinstance(item, dict):
ret_val = dict([
(hint_tuples(key, dict_key=True), hint_tuples(value))
for key, value in item.items()
])
else:
ret_val = item
return ret_val
return super(MultiDimensionalArrayEncoder, self).\
encode(hint_tuples(obj))
def hinted_tuple_hook(obj):
global tuple_signifier
ret_val = {}
if tuple_signifier in obj:
ret_val = tuple(json.loads(obj[tuple_signifier], object_hook=hinted_tuple_hook,))
else:
for k, v in obj.items():
inner_k = k
inner_v = v
if isinstance(k, str) and tuple_signifier in k:
inner_k = json.loads(k, object_hook=hinted_tuple_hook,)
if isinstance(v, str) and tuple_signifier in v:
inner_v = json.loads(v, object_hook=hinted_tuple_hook,)
ret_val[inner_k] = inner_v
return ret_val
#
# Some tests that show how to use the above hinted tuple hook to encode
# / decode Python tuples.
#
if __name__ == '__main__':
enc = MultiDimensionalArrayEncoder()
test_input_1 = (2,)
test_input_2 = {(2,): 'a'}
test_input_3 = {'a': {(2,): {1:'a'}}}
print('test_input_1 encoded:', enc.encode(test_input_1), test_input_1)
print('test_input_1 decoded:',
json.loads(enc.encode(test_input_1),
object_hook=hinted_tuple_hook,)
)
#"""
print('test_input_2 encoded:', enc.encode(test_input_2))
print('test_input_2 decoded:',
json.loads(enc.encode(test_input_2),
object_hook=hinted_tuple_hook,)
)
print('\n' * 3)
print('test_input_3 encoded:', enc.encode(test_input_3))
print('test_input_3 decoded:',
json.loads(enc.encode(test_input_3),
object_hook=hinted_tuple_hook,)
)
print('\n' * 3)
test_input_4 = {'a': 'b'}
print('test_input_4 encoded:', enc.encode(test_input_4))
print('test_input_4 decoded:',
json.loads(enc.encode(test_input_4),
object_hook=hinted_tuple_hook,)
)
#"""