查找和修改python嵌套字典(key,value)

2024-04-20 11:19:49 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个json文件需要更新。我将它转换为python dict(嵌套)来更新它。这是输入,但可以是任何部门。我相信有更好的方法来做这件事,但不知道。在

最后通牒除了更新之外,我还想执行创建/删除操作。在


这是脚本和输入文件

# Now find TARGET value in nested key value chain

# Replace old value with NEWVALUE

import json
from pprint import pprint
d1 = open('jinputstack.json', 'r')
d1 = json.load(d1)

def traverse(obj, path=None, callback=None):
    """
    Traverse Python object structure, calling a callback function for every element in the structure,
    and inserting the return value of the callback as the new value.
    """
    if path is None:
        path = []

    if isinstance(obj, dict):
        value = {k: traverse(v, path + [k], callback)
                 for k, v in obj.items()}
    elif isinstance(obj, list):
        value = [traverse(elem, path + [[]], callback)
                 for elem in obj]
    else:
        value = obj

    if callback is None:
        # print("Starting value Found-----------------------------------------------------")
        print(value)
        return value

    else:
        print(path, value)
        return callback(path, value)


def traverse_modify(obj, target_path, action):
    """
    Traverses any arbitrary object structure and performs the given action on the value, 
    replacing the node with the
    action's return value.
    """
    target_path = to_path(target_path)
    pprint(value)
    pprint(target_path)

    def transformer(path, value):
        if path == target_path:
            print(action)
            d2 = data["groups"][0]["properties"][1]["value"]["data"][2]["object"]["name"].update(action)
            return d2

        else:
            return value

    return traverse(obj, callback=transformer)


def to_path(path):
    """
    Helper function, converting path strings into path lists.
        >>> to_path('foo')
        ['foo']
        >>> to_path('foo.bar')
        ['foo', 'bar']
        >>> to_path('foo.bar[]')
        ['foo', 'bar', []]
    """
    if isinstance(path, list):
        return path  # already in list format

    def _iter_path(path):

        #pprint(path.split)

        for parts in path.split('[]'):
            for part in parts.strip('.').split('.'):
                yield part
            yield []

    return list(_iter_path(path))[:-1]

def updateit(newvalue):

    data["groups"][0]["properties"][1]["value"]["data"][2]["object"]["name"] = newvalue 
    print(data["groups"][0]["properties"][1]["value"]["data"][2]["object"]["name"])
    return data["groups"][0]["properties"][1]["value"]["data"][2]["object"]["name"]

traverse_modify(d1, d1["groups"][0]["properties"][1]["value"]["data"][1]["object"]["name"], updateit("XXXXXXXXXXXXXX"))

json_data = json.dumps(data)

f = open("jinputstack.json","w")
f.write(json_data)
f.close()

^{pr2}$

作者:文森特·德里森


Tags: thepathinjsonobjdatareturnobject
1条回答
网友
1楼 · 发布于 2024-04-20 11:19:49

我认为最好的方法是将Json对象转换为XML,并使用ElementTree和XPath来解析和修改对象。稍后,如果需要,可以恢复为Json:

import json
from xmljson import parker
from lxml.etree import Element

dataxml = parker.etree(datajson, root=Element('root'))
print(dataxml.find('.//data//name').text)            # John Su
dataxml.find('.//data//name').text = "Joan d'Arc"
print(dataxml.find('.//data//name').text)            # Joan d'Arc
print(json.dumps(parker.data(dataxml)))

有些包直接对Json字符串执行类似XPath的操作。{cd1>其中一个语法改变了。我更喜欢使用标准XPath语法。在

^{pr2}$

另一个非常简单,也许更容易学习的方法,与你现在所做的没有多大区别。在

import xjpath

xj = xjpath.XJPath(datajson)
print(xj['groups.@0.properties.@1.value.data.@1.object.name'])

# Not much different than your code:
print(data["groups"][0]["properties"][1]["value"]["data"][1]["object"]["name"])

我希望这有帮助。在

相关问题 更多 >