首页 > 解决方案 > Python:从 JSON 字符串加载带有数字键的字典(带有双引号键)

问题描述

>>> import json
>>> example = { 1: "banana", 2: "apple"}
>>> example
{1: 'banana', 2: 'apple'}
>>> json_example = json.dumps(example)
>>> json_example
'{"1": "banana", "2": "apple"}'
>>> from_str=json.loads(json_example)
>>> from_str
{'1': 'banana', '2': 'apple'}

我的问题很简单,但我找不到直接的解决方案......

从一个 json 编码的字符串(这里json_example),其中键代表数值,但是是双引号(因为 JSON 标准只允许双引号字符串作为属性键),我想加载一个键是数值的字典。

json.loads返回一个字典,其中键是字符串。如何将键作为数值?

编辑:

在大多数情况下,像@not_speshal提出的那样的单线是完全可以的。但是这个问题的上下文是一个 Django 表单(读取用户提供的 json 字符串)。我正在寻找可能涉及 JSON 解码器的解决方案。所以我可以将它作为参数传递给 Djangoforms.JSONField类,以避免继承这个类并编写大量特定于 Django 的代码。

标签: pythonjson

解决方案


我能想到的最直接的方法是检查加载的 dict 并将str键解析为ints ,就像@not_speshal在他们的评论中建议的那样。

{int(k): from_str[k] for k in from_str}

如果你想要一个函数调用来完成这个技巧,你可以使用object_hook参数。json.loads()这不会保存任何计算,因为该对象仍被读取为dict带有str键,然后您将其转换为int.

文档

object_hook是一个可选函数,将使用解码的任何对象字面量 (a dict) 的结果调用。将使用的返回值object_hook代替dict. 此功能可用于实现自定义解码器(例如 JSON-RPC 类提示)。

example = { 1: "banana", 2: "apple"}
json_example = json.dumps(example)

def parse_int_keys(dct):
    rval = dict()
    for key, val in dct.items():
        try:
            # Convert the key to an integer
            int_key = int(key)
            # Assign value to the integer key in the new dict
            rval[int_key] = val
        except ValueError:
            # Couldn't convert key to an integer; Use original key
            rval[key] = val
    return rval

from_str = json.loads(json_example, object_hook=parse_int_keys)
# from_str is now 
# {1: 'banana', 2: 'apple'}

这种方法的优点是它也适用于嵌套字典,而无需编写更多代码:

obj = {'a': 1, 'b': {1: 'abc'}, 0: [1, 2, 3], '1234': 'Hi!'}
json.loads(json.dumps(obj), object_hook=parse_int_keys)
# Output: 
# {'a': 1, 'b': {1: 'abc'}, 0: [1, 2, 3], 1234: 'Hi!'}

但是,请注意,最初是可以解析为整数的字符串(例如'1234'在我上面的示例中)的键仍将转换为整数,因为我们无法区分这两种情况。


推荐阅读