在Python中的嵌套json中使用字符串变量作为键
我有一个JSON对象,数据,我需要修改 现在,我正在修改对象,如下所示:在Python中的嵌套json中使用字符串变量作为键,json,python-3.x,Json,Python 3.x,我有一个JSON对象,数据,我需要修改 现在,我正在修改对象,如下所示: data['Foo']['Bar'] = 'ExampleString' 是否可以使用字符串变量进行索引 s = 'Foo/Bar' data[s.split('/')] = 'ExampleString' 上述代码不起作用。 我怎样才能达到我所追求的行为 注意:我正在寻找一种支持任意数量的关键级别的解决方案,例如字符串变量可能是Foo/Bar/Baz,或者Foo/Bar/Baz/Foo/Bar,它将对应于数据['Fo
data['Foo']['Bar'] = 'ExampleString'
是否可以使用字符串变量进行索引
s = 'Foo/Bar'
data[s.split('/')] = 'ExampleString'
上述代码不起作用。
我怎样才能达到我所追求的行为
注意:我正在寻找一种支持任意数量的关键级别的解决方案,例如字符串变量可能是Foo/Bar/Baz,或者Foo/Bar/Baz/Foo/Bar,它将对应于数据['Foo']['Bar']['Baz']和数据['Foo']['Baz']['Foo']['Bar'].一个非常简单的解决方案,可以让您朝正确的方向前进 您需要添加错误处理,例如,如果某个长路径中缺少一个键,会发生什么情况?你既可以退出,也可以在运行中添加新的命令
def update(path, d, value):
for nested_key in path.split('/'):
temp = d[nested_key]
if isinstance(temp, dict):
d = d[nested_key]
d[nested_key] = value
one_level_path = 'Foo/Bar'
one_level_dict = {'Foo': {'Bar': None}}
print(one_level_dict)
update(one_level_path, one_level_dict, 1)
print(one_level_dict)
two_level_path = 'Foo/Bar/Baz'
two_level_dict = {'Foo': {'Bar': {'Baz': None}}}
print(two_level_dict)
update(two_level_path, two_level_dict, 1)
print(two_level_dict)
输出
{'Foo': {'Bar': None}}
{'Foo': {'Bar': 1}}
{'Foo': {'Bar': {'Baz': None}}}
{'Foo': {'Bar': {'Baz': 1}}}
这是一个非常简单的解决方案,可以让您朝着正确的方向前进 您需要添加错误处理,例如,如果某个长路径中缺少一个键,会发生什么情况?你既可以退出,也可以在运行中添加新的命令
def update(path, d, value):
for nested_key in path.split('/'):
temp = d[nested_key]
if isinstance(temp, dict):
d = d[nested_key]
d[nested_key] = value
one_level_path = 'Foo/Bar'
one_level_dict = {'Foo': {'Bar': None}}
print(one_level_dict)
update(one_level_path, one_level_dict, 1)
print(one_level_dict)
two_level_path = 'Foo/Bar/Baz'
two_level_dict = {'Foo': {'Bar': {'Baz': None}}}
print(two_level_dict)
update(two_level_path, two_level_dict, 1)
print(two_level_dict)
输出
{'Foo': {'Bar': None}}
{'Foo': {'Bar': 1}}
{'Foo': {'Bar': {'Baz': None}}}
{'Foo': {'Bar': {'Baz': 1}}}
在不完全更改要使用的数据类的情况下,这可能是最简单的:
def jsonSetPath(jobj, path, item):
prev = None
y = jobj
for x in path.split('/'):
prev = y
y = y[x]
prev[x] = item
以迭代方式下降到对象中的包装器Python。然后你可以用
jsonSetPath(data, 'foo/obj', 3)
通常。如果愿意,可以通过继承dict将此功能添加到词典中:
class JsonDict(dict):
def __getitem__(self, path):
# We only accept strings in this dictionary
y = self
for x in path.split('/'):
y = dict.get(y, x)
return y
def __setitem__(self, path, item):
# We only accept strings in this dictionary
y = self
prev = None
for x in path.split('/'):
prev = y
y = dict.get(y, x)
prev[x] = item
注意:从集合中使用UserDict可能会被建议,但如果不将所有内部字典转换为用户字典,似乎会有很多麻烦。现在,您可以包装数据data=JsonDictdata并根据需要使用它。如果您想使用非字符串作为键,您需要处理它,尽管我不确定这在这个特定的字典实现中是否有意义
注意:只有外部字典是您的自定义字典。如果用例更高级,则还需要转换所有内部的用例,然后还可以使用UserDictionary。在不完全更改要使用的数据类的情况下,这可能是最简单的:
def jsonSetPath(jobj, path, item):
prev = None
y = jobj
for x in path.split('/'):
prev = y
y = y[x]
prev[x] = item
以迭代方式下降到对象中的包装器Python。然后你可以用
jsonSetPath(data, 'foo/obj', 3)
通常。如果愿意,可以通过继承dict将此功能添加到词典中:
class JsonDict(dict):
def __getitem__(self, path):
# We only accept strings in this dictionary
y = self
for x in path.split('/'):
y = dict.get(y, x)
return y
def __setitem__(self, path, item):
# We only accept strings in this dictionary
y = self
prev = None
for x in path.split('/'):
prev = y
y = dict.get(y, x)
prev[x] = item
注意:从集合中使用UserDict可能会被建议,但如果不将所有内部字典转换为用户字典,似乎会有很多麻烦。现在,您可以包装数据data=JsonDictdata并根据需要使用它。如果您想使用非字符串作为键,您需要处理它,尽管我不确定这在这个特定的字典实现中是否有意义
注意:只有外部字典是您的自定义字典。如果用例更高级,则还需要转换所有内部用例,然后还可以使用UserDictionary。使用递归:
使用递归:
是的,你可以做x=s.split'/';数据[x[0]][x[1]]?@shaikmoeed是的,但是如果元素的数量是可变的呢?例如Foo/Bar/baz你的字符串有点复杂吗?我的意思是像‘Foo/Bar/inner/first/smart/here’?@Ramesh是的,解决方案应该支持任意数量的字段。然后,你应该循环,直到到达最后一个元素。这就是你要找的吗?是的,你可以做x=s.split'/';数据[x[0]][x[1]]?@shaikmoeed是的,但是如果元素的数量是可变的呢?例如Foo/Bar/baz你的字符串有点复杂吗?我的意思是像‘Foo/Bar/inner/first/smart/here’?@Ramesh是的,解决方案应该支持任意数量的字段。然后,你应该循环,直到到达最后一个元素。这就是你想要的吗?子类化UserDict是一个有趣的想法。然后,可以将此行为烘焙到_getitem__中,因此不需要特殊的方法needed@DeepSpace我写的是asws:BTW,jsonGetPath将不起作用。您必须验证是否返回dict,否则将返回值。如果y[x]是a,你应该只做y=y[x]dict@DeepSpace我不管回哪一个。我为什么要这样做?如果给定一个值的路径,它在调用方上,不是吗?如果你认为数据是{Fo’:{ Bar’:{ BAZ’:没有}}},你将如何使用JPONETETPATH来将NO改为1?子类USEDICT是一个有趣的想法。然后,可以将此行为烘焙到_getitem__中,因此不需要特殊的方法needed@DeepSpace我写的是asws:BTW,jsonGetPath将不起作用。您必须验证是否返回dict,否则将返回值。如果y[x]是a,你应该只做y=y[x]dict@DeepSpace我不管回哪一个。我为什么要这样做?如果给定一个值的路径,它是在调用方上的,不是吗?如果你认为数据是{Fo’:{ Bar’:{ BAZ’:没有}}},你将如何使用JPONETETPATH来改变NO到1?谢谢你的回答。我决定使用@kabanus中的jsonSetPath,因为它在我看来更具可读性。谢谢你的回答。我决定使用@kabanus中的jsonSetPath,因为在我看来它更具可读性。