Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中的嵌套json中使用字符串变量作为键_Json_Python 3.x - Fatal编程技术网

在Python中的嵌套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

我有一个JSON对象,数据,我需要修改

现在,我正在修改对象,如下所示:

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,因为在我看来它更具可读性。