2

Consider this snippet:

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

My attempt was to pass a Python dict to json.dumps(), and then use json.loads() to get it back. But that doesn't happen, probably because JSON alays considers keys as strings.

Is there any other way I can retain the original key types?

4

2 回答 2

1

将 Python dicts 中的整数键转换为符合 JSON 标准的字符串键json.dumps()有损的:一旦完成,就无法判断原始键是整数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}
于 2018-01-22T21:33:32.057 回答
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'}

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

于 2018-01-22T19:59:33.393 回答