Python JSON - 查找动态路径上的元素

Sim*_*onB 7 python

我必须更新嵌套的 JSON 对象。
如果我知道要更新哪些项目的具体细节,我可以这样做:

json_object['basket']['items']['apple'] = 'new value'
Run Code Online (Sandbox Code Playgroud)

然而,我的目标元素列表是动态的。

> basket.items.apple = 'green'
> name = 'my shopping'
> basket.cost = '15.43'
Run Code Online (Sandbox Code Playgroud)

我可以通过循环元素来做到这一点。
查找“篮子”> 然后查找“项目”> 然后查找“苹果”> 设置值
查找“名称”> 设置值

然而,希望有一种方法可以直接/动态引用。
即从字符串'basket.cost'构建表达式:

json_object['basket']['cost']
Run Code Online (Sandbox Code Playgroud)

PS它也必须处理字典列表!

任何指导表示赞赏:)

Pra*_*adi 2

获得字符串后"basket.cost",您可以将其拆分".",并且很容易json_object['basket']['cost']使用循环进行深入研究。从功能上讲,这样做和“直接”这样做没有区别:您仍然首先获取密钥'basket',然后'cost'从 的值中获取密钥json_object['basket']

def get_element(d, path):
    # This function can take the string "basket.cost", or the list ["basket", "cost"]
    if isinstance(path, str):
        path = path.split(".")

    for p in path:
        d = d[p]

    return d

def set_element(d, path, value):
    path = path.split(".")
    dict_to_set = get_element(d, path[:-1])
    key_to_set = path[-1]
    dict_to_set[key_to_set] = value

set_element(json_object, "basket.items.apple", 100)
Run Code Online (Sandbox Code Playgroud)

现在,假设路径的所有元素都已存在,所以假设您创建了一个如下所示的字典:

json_object = {"basket": {"items": dict()}}
set_element(json_object, "basket.items.apple", 100)
set_element(json_object, "basket.cost", 10)
print(json_object) 
# Output: {'basket': {'items': {'apple': 100}, 'cost': 10}}

print(get_element(json_object, "basket.cost")) 
# Output: 10
Run Code Online (Sandbox Code Playgroud)

如果您尝试访问尚不存在的元素,您会得到KeyError

get_element(json_object, "basket.date")
# KeyError: 'date'
Run Code Online (Sandbox Code Playgroud)

如果您尝试在不存在的元素中设置值,也会发生这种情况:

set_element(json_object, "basket.date.day", 1)
# KeyError: 'date'
Run Code Online (Sandbox Code Playgroud)

如果我们想让您的函数在字典不存在时创建它们,我们可以修改该get_element函数以解决这种情况并添加密钥:

def get_element(d, path, create_missing=False):
    # This function can take the string "basket.cost", or an iterable containing the elements "basket" and "cost"
    if isinstance(path, str):
        path = path.split(".")

    for p in path:
        if create_missing and p not in d:
            d[p] = dict()

        d = d[p]

    return d

def set_element(d, path, value, create_missing=True):
    path = path.split(".")
    dict_to_set = get_element(d, path[:-1], create_missing)
    key_to_set = path[-1]
    dict_to_set[key_to_set] = value

set_element(json_object, "basket.date.day", 1)
print(json_object)
# Output: {'basket': {'items': {'apple': 100}, 'cost': 10, 'date': {'day': 1}}}
Run Code Online (Sandbox Code Playgroud)