问题描述
我将 JSON 文件解析为字典,示例 JSON 数据如下
{
"environmental": {
"temprature": {
"test" : "temprature","unit": "c","Now": 12.65,"Now_timestamp": "10-06-2019 08:02:18","min": "12.5","min_timestamp": "03-06-2019 07:40:02","max": "32.84","max_timestamp": "03-06-2019 04:30:03"
}
}
}
我想使用列表元组或字符串作为字典键检索值或设置值。
var_lst_key = ["environmental","temprature","Now"]
var_dict_x[var_lst_key] = "x"
或
print(var_dict_x[var_lst_key])
解决方法
第 1 部分:使用简单的方法:使用函数
嵌套查找非常容易。您遍历键,并不断用您当前正在查看的键的值替换您正在查看的对象:
def nested_get(obj,keys):
for key in keys:
obj = obj[key]
return obj
def nested_set(obj,keys,value):
for key in keys[:-1]:
# Drill down until the penultimate key
obj = obj[key]
# Set value of last key
obj[keys[-1]] = value
运行:
jstr = """{ "environmental": {
"temprature": {
"test" : "temprature","unit": "c","now": 12.65,"now_timestamp": "10-06-2019 08:02:18","min": "12.5","min_timestamp": "03-06-2019 07:40:02","max": "32.84","max_timestamp": "03-06-2019 04:30:03"
}
}}"""
jobj = json.loads(jstr)
var_lst_key = ["environmental","temprature","now"]
nested_lookup(jobj,var_lst_key) # Returns 12.65
invalid_keys = ["environmental","hello"]
nested_lookup(jobj,invalid_keys) # throws KeyError 'hello'
nested_set(jobj,var_lst_key,"HELLO!")
nested_lookup(jobj,var_lst_key) # Returns HELLO!
第 2 部分:以奇特的方式实现:使用派生类
现在,如果您真的想要使用 dict[key] = value
语法,您将不得不扩展 dict
类以覆盖其 __getitem__()
和 { {1}} 个方法。
__setitem__()
要使用这个,让我们像以前一样使用从字符串中解析出来的 json 对象:
class NestedLookupDict(dict):
def __init__(self,*args,**kwargs):
super(type(self),self).__init__(*args,**kwargs)
self.insert_missing_keys = True
def __getitem__(self,indices):
# Get the super dictionary for easy lookup
obj = self
for i in indices:
obj = dict.__getitem__(obj,i)
return obj
def __setitem__(self,indices,value):
# Get the base dictionary
obj = self
# Drill down until the penultimate key
for i in indices[:-1]:
# Insert a new dict if a key is missing
if self.insert_missing_keys and not dict.__contains__(obj,i):
dict.__setitem__(obj,i,dict())
obj = dict.__getitem__(obj,i)
# Set the value at the final key
dict.__setitem__(obj,indices[-1],value)
当 # jobj = {... something ...}
nested_dict = NestedLookupDict(jobj)
print(nested_dict[var_lst_key]) # Prints 12.65
nested_dict[var_lst_key] = "HELLO!"
print(nested_dict[var_lst_key]) # Prints HELLO!
设置为 nested_dict.insert_missing_keys
(默认情况下)时,True
方法会根据需要添加缺失的字典。
__setitem__()
在这一切结束时,您可以将对象转储到 json 中以查看它的外观:
newkey = ["environmental","newkey"]
nested_dict[newkey] = "NEWKEY!!!"
print(nested_dict[newkey]) # Prints NEWKEY!!!
newkey2 = ["environmental","nested","newkey"]
nested_dict[newkey2] = "NESTEDNEWKEY!!!"
print(nested_dict[newkey2]) # Prints NESTEDNEWKEY!!!
第 3 部分:太过分了,但是哦!编写代码非常有趣:添加 NestedLookupDict
附加功能,以便您可以像使用 print(json.dumps(nested_dict))
# Output:
{
"environmental": {
"temprature": {
"test": "temprature","now": "HELLO!","max_timestamp": "03-06-2019 04:30:03","newkey": "NEWKEY!!!","nested": {
"newkey": "NESTEDNEWKEY!!!"
}
}
}
}
一样使用它:
- 使用
dict
删除密钥 - 使用
del nested_dict[key]
检查密钥是否存在 -
key in nested_dict
如果nested_dict.get(key,default)
不存在,则吸收KeyError
,并返回key
- 对
default
实施类型检查:它们现在必须是keys
或list
怪癖:
- 由于
tuple
的实现方式,__getitem__()
返回对nested_dict[empty_list]
(本身)的引用。如果这是一件坏事,可以添加对空键的检查。但是,我认为以这种方式离开它没有任何问题。这种怪癖的一些后果:- 为了使此行为与
nested_dict
的工作方式一致,__contains__()
函数为空__contains__()
返回True
。key
- 根据定义,您不能设置
[] in nested_list := True
。这会引发 ValueError
- 为了使此行为与
nested_list[[]]
,
您可以使用 json 并将其作为 dict 加载,如下所示:
# importing the module
import json
# Opening JSON file
with open('data.json') as json_file:
data = json.load(json_file)
# Print the type of data variable
print("Type:",type(data))
# Print the data of dictionary
print("\nPeople1:",data['people1'])
print("\nPeople2:",data['people2'])
以下代码使用键从字典中输出每个元素