我可以无损地恢复json.dumps()已转换为字符串的整数键吗?

时间:2018-01-22 19:57:39

标签: python json roundtrip

请考虑以下代码段:

>>> import json
>>> a = {1:'1'}
>>> json_a = json.dumps(a)
>>> json.loads(json_a)
{'1': '1'}

我的尝试是将Python dict传递给json.dumps(),然后使用json.loads()将其恢复。但这不会发生,可能是因为JSON alays将键视为字符串。

还有其他方法可以保留原始密钥类型吗?

2 个答案:

答案 0 :(得分:1)

json.dumps()将Python dicts中的整数键转换为符合JSON标准的字符串键是有损:一旦完成,就无法判断原始密钥是否为整数23或字符串'23'(除非该信息存储在别处)。

也就是说,可以强制json.loads()尽可能将密钥转换为整数,方法是将适当的函数作为object_pairs_hook参数传递:

 def int_keys(ordered_pairs):
    result = {}
    for key, value in ordered_pairs:
        try:
            key = int(key)
        except ValueError:
            pass
        result[key] = value
    return result

用法:

>>> import json
>>> data = {1: '1', 2: '2', 3: '3'}
>>> text = json.dumps(data)
>>> text
'{"1": "1", "2": "2", "3": "3"}'
>>> json.loads(text, object_pairs_hook=int_keys)
{1: '1', 2: '2', 3: '3'}

对此进行扩展,也可以编写object_pairs_hook,它不仅可以转换整数,还可以转换json.dumps()可能转换为字符串的所有其他非字符串键:

SPECIAL = {
    "true": True,
    "false": False,
    "null": None,
}

def round_trip(ordered_pairs):
    result = {}
    for key, value in ordered_pairs:
        if key in SPECIAL:
            key = SPECIAL[key]
        else:
            for numeric in int, float:
                try:
                    key = numeric(key)
                except ValueError:
                    continue
                else:
                    break
        result[key] = value

用法:

>>> print(more_text)
{
  "2": 2,
  "3.45": 3.45,
  "true": true,
  "false": false,
  "null": null,
  "Infinity": Infinity,
  "-Infinity": -Infinity,
  "NaN": NaN
}
>>> json.loads(more_text, object_pairs_hook=round_trip)
{2: 2, 3.45: 3.45, True: True, False: False, None: None, inf: inf, -inf: -inf, nan: nan}

答案 1 :(得分:0)

我们可以使用str(value)代替json.dumps(value)ast.literal_eval()代替json.loads()

>>> a = {1: "1"}
>>> a_as_string = str(a)
>>> import ast 
>>> ast.literal_eval(a_as_string)
{1: '1'}

刚刚发布作为初始解决方案,期待更复杂的解决方案。