从嵌套的json文件中删除python dict项

Remove python dict item from nested json file

当我试图删除python dict中的项时,我从返回keyror:0的API中获取了一个json文件。我认为它是我缺乏技能和json格式的结合。

我的目标是从ip_address_1中删除192.168.1.1的所有实例。

我的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from api import Request
import requests, json, ordereddict

# prepare request
request = Request().service('').where({"query":"192.168.1.0"}).withType("json")

# call request
response = request.execute()

# parse response into python object
obj = json.loads(response)

# remove items
for i in xrange(len(obj)):
    if obj[i]["ip_address_1"] =="192.168.1.1":
        obj.pop(i)

# display
print json.dumps(obj,indent=1)

JSON示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
"response": {
 "alerts": [
   {
   "action":"New",
   "ip_address_1":"192.168.1.1",
   "domain":"example.com",
   "ip_address_2":"192.68.1.2"
   },
   {
   "action":"New",
   "ip_address_1":"192.168.1.3",
   "domain":"example2.com",
   "ip_address_2":"192.168.1.1"
   }
  ],
 "total":"2",
 "query":"192.168.1.0",
 }
}


这是不正确的:

1
2
3
4
# remove items
for i in xrange(len(obj)):
    if obj[i]["ip_address_1"] =="192.168.1.1":
        obj.pop(i)

您正在迭代一个对象,就像它是一个列表一样。

你想做的:

1
2
3
for sub_obj in obj["response"]["alerts"]:
    if sub_obj["ip_address_1"] =="192.168.1.1":
        sub_obj.pop("ip_address_1")


我已将您的要求解释为:

  • 从"警报"列表中删除设置了ip_address_1的任何字典。到192.168.1.1
  • 创建所有其他ip_address_1值的列表。
  • json.loads(response)生成本词典:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    {u'response': {u'alerts': [{u'action': u'New',
                                u'domain': u'example.com',
                                u'ip_address_1': u'192.168.1.1',
                                u'ip_address_2': u'192.68.1.2'},
                               {u'action': u'New',
                                u'domain': u'example2.com',
                                u'ip_address_1': u'192.168.1.3',
                                u'ip_address_2': u'192.168.1.1'}],
                   u'query': u'192.168.1.0',
                   u'total': u'2'}}

    "警报"列表的访问方式(假设dict绑定到obj上):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    >>> obj['response']['alerts']
    [{u'action': u'New',
      u'domain': u'example.com',
      u'ip_address_1': u'192.168.1.1',
      u'ip_address_2': u'192.68.1.2'},
     {u'action': u'New',
      u'domain': u'example2.com',
      u'ip_address_1': u'192.168.1.3',
      u'ip_address_2': u'192.168.1.1'}]

    第一部分可以这样做:

    1
    2
    alerts = obj['response']['alerts']
    obj['response']['alerts'] = [d for d in alerts if d.get('ip_address_1') != '192.168.1.1']

    在这里,列表理解被用来过滤那些带有ip_address_1192.168.1.1的字典,然后返回到obj字典。在此之后,obj是:

    1
    2
    3
    4
    5
    6
    7
    >>> pprint(obj)
    {u'response': {u'alerts': [{u'action': u'New',
                                u'domain': u'example2.com',
                                u'ip_address_1': u'192.168.1.3',
                                u'ip_address_2': u'192.168.1.1'}],
                   u'query': u'192.168.1.0',
                   u'total': u'2'}}

    接下来,创建其他IP地址的列表很容易,删除不需要的dict后,在警报列表上运行另一个列表理解,如上图所示:

    1
    ip_addresses = [d['ip_address_1'] for d in obj['response']['alerts'] if d.get('ip_address_1') is not None]

    注意,我们使用get()来处理某些字典可能没有ip_address_1键的可能性。

    1
    2
    >>> ip_addresses
    [u'192.168.1.3']