【问题标题】:Read a JSON and convert the keys to int读取 JSON 并将密钥转换为 int
【发布时间】:2019-04-02 16:11:29
【问题描述】:

众所周知,json 将 dict 的整数键转换为字符串:

import json
print json.dumps({1: [2.5, 2.5, 2.5], 2: [3, 3, 3, 3]})
# {"1": [2.5, 2.5, 2.5], "2": [3, 3, 3, 3]}

在加载整数键时最干净的方法是什么?

d = json.loads('{"1": [2.5, 2.5, 2.5], "2": [3, 3, 3, 3]}')
print d
# {u'1': [2.5, 2.5, 2.5], u'2': [3, 3, 3, 3]}

我在想:

d = {int(k): d[k] for k in d}

但是有没有一种更简洁的方法来处理带有 JSON / Python 整数键的字典,而不需要后验的键转换?

【问题讨论】:

  • 用什么方式清理?你可以做{int(k):v for k,v in d.items()}
  • @juanpa.arrivillaga 为了避免转换,将其作为带有整数键的字典直接加载。
  • 好吧,由于 JSON 需要字符串键,您要么必须编写自己的解码器(使用 json 库很简单),要么直接转换,或者选择另一种序列化格式。跨度>
  • @juanpa.arrivillaga 嗯,好的,我想这就是答案(如果你想发布的话)。

标签: python json dictionary


【解决方案1】:

使用object_hook定义自定义函数并执行操作:

import json

def keystoint(x):
    return {int(k): v for k, v in x.items()}

j = json.dumps({1: [2.5, 2.5, 2.5], 2: [3, 3, 3, 3]})
# {"1": [2.5, 2.5, 2.5], "2": [3, 3, 3, 3]}

print(json.loads(j, object_hook=keystoint))
# {1: [2.5, 2.5, 2.5], 2: [3, 3, 3, 3]}

来自docs

object_hook 是一个可选函数,将使用 任何对象文字解码的结果(字典)。返回值 将使用object_hook 代替字典。


或者,您也可以使用 object_pairs_hook 来遍历对并保存 .items() 调用(感谢 @chepner):
import json

def keystoint(x):
    return {int(k): v for k, v in x}

j = json.dumps({1: [2.5, 2.5, 2.5], 2: [3, 3, 3, 3]})
# {"1": [2.5, 2.5, 2.5], "2": [3, 3, 3, 3]}

print(json.loads(j, object_pairs_hook=keystoint))
# {1: [2.5, 2.5, 2.5], 2: [3, 3, 3, 3]}

来自文档:

object_pairs_hook 是一个可选函数,将使用 使用有序对列表解码的任何对象文字的结果。 将使用 object_pairs_hook 的返回值,而不是 字典。

【讨论】:

  • object_pairs_hook 稍微简单一些(保存对items 方法的调用),因为它接收的是键/值对列表而不是字典。 loads(j, object_pairs_hook=lambda pairs: {int(k): v for k,v in pairs}).
  • @chepner,好点子。当然,如果大小更大,保存.items() 调用应该很重要。
  • 默认解码器至少总是在内存中构建一个具体的键/值对列表。 object_pairs_hook 通过直接在该列表上操作来缩短正常进程;否则,列表首先变成dict,要么按原样返回,要么传递给object_hook(即,给定pairs,解码器返回object_pairs_hook(pairs)dict(pairs)object_hook(dict(pairs)) .)
【解决方案2】:

如果您有嵌套字典,我还想添加另一个解决方案。


我在另一个处理普通字典的问题下看到this solution,如果您在第二层中有非整数键,则 nested dictionaries 会出错。
>>> import json
>>> json_data = '{"1": "one", "2": {"-3": "minus three", "4": "four"}}'
>>> py_dict = json.loads(json_data, object_hook=lambda d: {int(k) 
                         if k.lstrip('-').isdigit() else k: v for k, v in d.items()})
>>> py_dict
{1: 'one', 2: {-3: 'minus three', 4: 'four'}}

我们可以看到object_hook是用来解决问题的,lstrip('-')也是用来处理负值的。

【讨论】:

    猜你喜欢
    • 2018-04-11
    • 2020-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-15
    • 2019-09-12
    • 2016-11-18
    • 2021-10-14
    相关资源
    最近更新 更多