如果不存在则跳过json密钥

时间:2016-07-07 14:55:42

标签: python json python-2.7

我正在运行以下内容:

for server in server_list:
    for item in required_fields:
        print item, eval(item)

某些密钥可能不存在,但更糟糕的是它在父密钥上表示而不是我正在扫描的密钥。

所以我正在扫描json以获取以下密钥:

server['server_management']['server_total_cost_of_ownership']['description']

哪个不存在,但它实际上是null的父级:

server['server_management']['server_total_cost_of_ownership']

如何编写代码来解释此问题?它没有给出关键错误。现在我得到以下追溯:

Traceback (most recent call last):
  File "C:/projects/blah/scripts/test.py", line 29, in <module>
    print item, eval(item)
  File "<string>", line 1, in <module>
TypeError: 'NoneType' object has no attribute '__getitem__'

完整代码:

import csv
import json
import os
import requests
import sys

required_fields = ["server['server_name']","server['server_info']['asset_type']['display_name']",
                   "server['asset_status']['display_name']", "server['record_owner']['group_name']",
                   "server['server_management']['server_total_cost_of_ownership']['description']",
                   "server['server_management']['primary_business_owner']['name']",
                   "server['environment']['display_name']", "server['is_virtual']",
                   "server['managed_by']['display_name']", "server['server_info']['billable_ibm']",
                   "server['server_info']['billing_sub_type']['display_name']",
                   "server['server_info']['serial_number']", "server['location']['display_name']",
                   "server['inception_date']", "server['server_info']['decommission_date']" ]

# Query API for all servers
def get_servers_info():
    servers_info = requests.get('url')
    return servers_info.json()

def get_server_info(sid):
    server_info = requests.get('url')
    return server_info.json()

server_list = get_servers_info()
for server in server_list:
    for item in required_fields:
        print item, eval(item)

3 个答案:

答案 0 :(得分:2)

实际上你应该避免使用eval。在您知道密钥名称之后加载json之后,您可以使用列表在树中更深入。

server['server_management']['primary_business_owner']['name']" => ["server_management', 'primary_business_owner', 'name']

这是针对必填字段列表进行json验证的片段。

data={
    "d": {
        "p":{
            "r":[
                "test"
            ]
        }
    },
    "a": 3
}


def _get_attr(dict_, attrs):
    try:
        src = attrs[:]
        root = attrs.pop(0)
        node = dict_[root]
        null = object()
        for i, attr in enumerate(attrs[:]):
            try:
                node = node.get(attr, null)
            except AttributeError:
                node = null
            if node is null:
                # i+2 pop and last element
                raise ValueError("%s not present (level %s)" % (attr, '->'.join(src[: i+2])))
        return node
    except KeyError:
        raise ValueError("%s not present" % root)

# assume list of required field
reqs = [
    ["d", "p", "r"],
    ["d"],
    ["k"],
    ["d", "p", "r", "e"],
]

for req in reqs:
    try:
        _get_attr(data, req)
    except ValueError as E:
        print(E)
# prints
# k not present
# e not present (level d->p->r->e)

答案 1 :(得分:0)

忽略代码的上下文而不理解eval的使用,这样做的方法是使用.get()并使用合理的默认值对其进行种子化。

例如:

server['server_management']['server_total_cost_of_ownership']['description']

可以:

server.get('server_management', {}).get('server_total_cost_of_ownership', {}).get('description', '')

然后,如果任何一个键不存在,您将始终返回一个空的描述&#39;&#39;。

答案 2 :(得分:0)

此处的问题与使用eval [1]完全无关。您得到的例外情况与代码直接存在的情况相同。您正在运行的内容(通过eval)是:

a = server['server_management']
b = a['server_total_cost_of_ownership']
c = b['description']

然而,bNone,因此将其解析为c将会失败。与KeyError一样,您也可以抓住TypeError

for server in server_list:
  for item in required_fields:
    try:
      print item, eval(item)
    except TypeError:
      print("Guess you're lucky you didn't include a fork bomb in your own code to eval.")

您当然可以选择pass,打印违规项目,打开a browser to some page或根据输入数据执行任何适当的错误处理。

[1]虽然没有争吵,但我made a new answer that works without eval。您可以使用完全相同的错误处理:

for server in server_list:
  for item in required_fields:
  value = server
  for key in parse_fields(field):
    try:
      value = value[key]
    except TypeError:
      print("Remember Kiddo: Eval is Evil!")
      break
  else:  # for: else: triggers only if no break was issued
    print item, value