簡體   English   中英

在Python中更新復雜的JSON對象

[英]Updating complex JSON object in Python

我正在使用Python(v3.5)抓取一些復雜的MongoDB文檔,我應該更新其中散布在對象周圍的一些值,並且在結構中沒有特定的模式,並將其保存回不同的MongoDB集合。 該對象如下所示:

# after json.loads(mongo_db_document) my dict looks like this
notification = {
    '_id': '570f934f45213b0d14b1256f',
    'key': 'receipt',
    'label': 'Delivery Receipt',
    'version': '0.0.1',
    'active': True,
    'children': [
        {
            'key': 'started',
            'label': 'Started',
            'children': [
                'date',
                'time',
                'offset'
            ]
        },
        {
            'key': 'stop',
            'label': 'Ended',
            'children': [
                'date',
                'time',
                'offset'
            ]
        },
        {
            'label': '1. Particulars',
            'template': 'formGroup',
            'children': [
                {
                    'children': [
                        {
                            'key': 'name',
                            'label': '2.1 Name',
                            'value': '********** THIS SHOULD BE UPDATED **********',
                            'readonly': 'true'
                        },
                        {
                            'key': 'ims_id',
                            'label': '2.2 IMS Number',
                            'value': '********** THIS SHOULD BE UPDATED **********',
                            'readonly': 'true'
                        }
                    ]
                },
                {
                    'children': [
                        {
                            'key': 'type',
                            'readonly': '********** THIS SHOULD BE UPDATED **********',
                            'label': '2.3 Type',
                            'options': [
                                {
                                    'label': 'Passenger',
                                    'value': 'A37'
                                },
                                {
                                    'label': 'Cargo',
                                    'value': 'A35'
                                },
                                {
                                    'label': 'Other',
                                    'value': '********** THIS SHOULD BE UPDATED **********'
                                }
                            ]
                        }
                    ]
                }
            ]
        },
        {
            'template': 'formGroup',
            'key': 'waste',
            'label': '3. Waste',
            'children': [
                {
                    'label': 'Waste',
                    'children': [
                        {
                            'label': 'Plastics',
                            'key': 'A',
                            'inputType': 'number',
                            'inputAttributes': {
                                'min': 0
                            },
                            'value': '********** THIS SHOULD BE UPDATED **********'
                        },
                        {
                            'label': 'B. Oil',
                            'key': 'B',
                            'inputType': 'number',
                            'inputAttributes': {
                                'min': 0
                            },
                            'value': '********** THIS SHOULD BE UPDATED **********'
                        },
                        {
                            'label': 'C. Operational',
                            'key': 'C',
                            'inputType': 'number',
                            'inputAttributes': {
                                'min': 0
                            },
                            'value': '********** THIS SHOULD BE UPDATED **********'
                        }
                    ]
                }
            ]
        },
        {
            'template': 'formRow',
            'children': [
                'empty',
                'signature'
            ]
        }
    ],
    'filter': {
        'timestamp_of_record': [
            'date',
            'time',
            'offset'
        ]
    }
}

我最初的想法是將占位符(如$var_name )放在需要更新值的位置,並使用Python的string.Template加載字符串,但遺憾的是,由於某種原因,這種方法會將大量內容泄露給同一MongoDB文檔的其他用戶。

有沒有一個解決方案來簡單地修改這種對象而沒有“硬編碼”路徑來找到我需要更新的值?

不確定我是否理解正確,但這將動態地找到所有鍵“值”和“只讀”並打印出解決字段的路徑。

def findem(data, trail):
    if isinstance(data, dict):
        for k in data.keys():
            if k in ('value', 'readonly'):
                print("{}['{}']".format(trail, k))
            else:
                findem(data[k], "{}['{}']".format(trail, k))
    elif isinstance(data, list):
        for k in data:
            findem(k, '{}[{}]'.format(trail, data.index(k)))

if __name__ == '__main__':
    findem(notification, 'notification')

notification['children'][2]['children'][0]['children'][0]['readonly']
notification['children'][2]['children'][0]['children'][0]['value']
notification['children'][2]['children'][0]['children'][1]['readonly']
notification['children'][2]['children'][0]['children'][1]['value']
notification['children'][2]['children'][1]['children'][0]['readonly']
notification['children'][2]['children'][1]['children'][0]['options'][0]['value']
notification['children'][2]['children'][1]['children'][0]['options'][1]['value']
notification['children'][2]['children'][1]['children'][0]['options'][2]['value']
notification['children'][3]['children'][0]['children'][0]['value']
notification['children'][3]['children'][0]['children'][1]['value']
notification['children'][3]['children'][0]['children'][2]['value']

這是我幾年前寫的這個小腳本 - 我用它來查找一些非常長且令人不安的JSON中的條目。 不可否認,這不是很美,但也許對你的情況有幫助嗎?
你可以在這里找到Bitbucket上的腳本( 這里是代碼)。 不幸的是,沒有記錄; 當時我並不是真的相信其他人會使用它,我想。
無論如何,如果您想嘗試它,請將腳本保存在您的工作目錄中,然后使用以下內容:

from RecursiveSearch import Retriever

def alter_data(json_data, key, original, newval):
    '''
    Alter *all* values of said keys
    '''
    retr = Retriever(json_data)
    for item_no, item in enumerate(retr.__track__(key)): # i.e. all 'value'
        # Pick parent objects with a last element False in the __track__() result,
        # indicating that `key` is either a dict key or a set element
        if not item[-1]: 
            parent = retr.get_parent(key, item_no)
            try:
                if parent[key] == original:
                    parent[key] = newval
            except TypeError:
                # It's a set, this is not the key you're looking for
                pass

if __name__ == '__main__':
    alter_data(notification, key='value', 
               original = '********** THIS SHOULD BE UPDATED **********',
               newval = '*UPDATED*')

不幸的是,正如我所說的那樣,腳本沒有很好的記錄,所以如果你想嘗試它並需要更多信息,我很樂意提供它。

將另一個列表添加到JSON對象。 該列表中的每個項目都是導致要更改的值的鍵列表。 一個這樣的列表的示例是: ['children', 2, 'children', 'children', 0, 'value'] 然后,要訪問該值,您可以使用循環:

def change(json, path, newVal):
    cur = json
    for key in path[:-1]:
        cur = cur[key]
    cur[path[-1]] = newVal

path = notification['paths'][0]
#path, for example, could be ['children', 2, 'children', 'children', 0, 'value']
newVal = 'what ever you want'
change(notification, path, newVal)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM