如何清理特定键的动态python字典?

2024-05-08 19:06:39 发布

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

这是一个相当迟钝的问题,没有一个典型的答案是冒泡到顶部。

我正在开发的工具的性质决定了我们使用MongoDB来存储大约25种不同工具的“设置”。每个工具都有自己的设置模式,因此每个文档都是不同的,但它们都存储在同一个集合中,并在由json模式绘制的同一个编辑页面上进行编辑。

由于不知道字典的模式,我正在努力找出如何迭代和清理数据,特别是删除密码。

给定下面的字典,并且知道其他dict可能有不同的模式,那么我如何遍历dict中的每一项并创建一个完全相同的拷贝,除了去掉任何key==“password”之外?

所以:

{
  "_enabled": true,
  "instances": [
    {
      "isdefault": true,
      "name": "dev",
      "password": "abc123",
      "url": "http://dev.example.com",
      "user": "buffy"
    },
    {
      "isdefault": false,
      "name": "prod",
      "password": "xxxxx",
      "url": "http://prod.example.com",
      "user": "spike"
    },
    {
      "isdefault": false,
      "name": "qa",
      "password": "dasddf",
      "url": "http://prod.example.com",
      "user": "willow"
    }
  ],
  "label": "MyServers"
}

应导致:

^{pr2}$

Tags: 工具namecomtruehttpurl编辑字典
3条回答

首先深度复制dict,然后捕获所有字典并删除密码键:

from copy import deepcopy

def remove_pass(v):
    if isinstance(v, dict):
        if "password" in v:
            del v["password"]
        for ele in v.values():
            remove_pass(ele)
    elif isinstance(v, Iterable) and not isinstance(v, basestring):
        for ele in v:
            remove_pass(ele)


from pprint import pprint as pp
d = deepcopy(d)
for v in d.values():
   remove_pass(v)

输入:

^{pr2}$

输出:

{'_enabled': 'true',
 'foo': {'isdefault': 'false',
         'name': 'qa',
         'nested': {},
         'url': 'http://prod.example.com',
         'user': 'willow'},
 'instances': [{'isdefault': 'true',
                'name': 'dev',
                'url': 'http://dev.example.com',
                'user': 'buffy'},
               {'isdefault': 'false',
                'name': 'prod',
                'nested': {'more_nesting': {'even_more_nesting': ({}, {})}},
                'url': 'http://prod.example.com',
                'user': 'spike'},
               {'isdefault': 'false',
                'name': 'qa',
                'url': 'http://prod.example.com',
                'user': 'willow'}],
 'label': 'MyServers'}

假设您只想检查列表或字典的容器,并从具有key = "password"的字典条目中删除键值对

#first copy the structure
new_data = copy.deepcopy(data)

#this is a recursive function. 
#Heavily nested structures may fail due to recursion limit
def clean_hierarchy(ele):
    #lists may contain dictionaries, so clean theses entries
    if isinstance(ele,list):
        for val in ele:
            clean_hierarchy(val)
    if isinstance(ele,dict):
        #remove possible password entry
        if "password" in ele:
            ele.pop("password",None)
        #dictionary may contain more dictionaries. Rinse and repeat!
        for val in ele.values():
            clean_hierarchy(val)

clean_hierarchy(new_data)

如果您知道每个数据的结构(也就是说,在数组/字典的深度中应该有“password”键),这就很简单了。您只需在列表项和字典中循环查找“password”键。在

如果每个设置字典的结构都是不可预测的,那么你就必须想出一个解决方案。在这种情况下,我所做的就是将我的JSON转储到一个字符串中,使用regex删除/隔离我感兴趣的数据,然后将字符串加载回结构化JSON。在

像这样:

导入json,re

raw_data = """{
  "_enabled": true,
  "instances": [
    {
      "isdefault": true,
      "name": "dev",
      "password": "abc123",
      "url": "http://dev.example.com",
      "user": "buffy"
    },
    {
      "isdefault": false,
      "name": "prod",
      "password": "xxxxx",
      "url": "http://prod.example.com",
      "user": "spike"
    },
    {
      "isdefault": false,
      "name": "qa",
      "password": "dasddf",
      "url": "http://prod.example.com",
      "user": "willow"
    }
  ],
  "label": "MyServers"
}"""

# I load and then dump my raw_data just to iron out any inconsistencies 
# in formatting before applying regex. i.e., inconsistent use of " instead of '
structured_data = json.loads(raw_data)
dumped_data = json.dumps(structured_data)

scrubbed = re.sub(r'"password": ".*?",', '', dumped_data)
structured_scrubbed = json.loads(scrubbed)

结果:

^{pr2}$

相关问题 更多 >