Iterating though a relatively consistent JSON file using try statements in Python
我有一个关于使用try/except语句在Python中迭代JSON文件的最佳实践问题。
我有一个JSON文件,看起来像这样(这个问题简化了很多):
1 2 3 4 5 6 7 8 9 10 11 12 | "results": [ { "listingId":"1" "address":"123 Main st" "landsize":"190 m2" }, { "listingId":"2" "address":"345 North st" "state":"California" } ] |
正如我所说,这是非常简单的(在我的实际问题中,有大约30个我感兴趣的键值对,以及数千条记录),挑战是,即使这些键非常一致(总是在30左右),偶尔也会有一个缺少的键值对。
如果缺少一个或两个或10个,我将希望记录的其余部分被写出,因此我目前的方法是对每个键值对使用一个try/catch语句,这似乎是一种非常低效的检查方法,我相信有更好的方法。
我的代码看起来(有点)像这样(我确信这不是最好的方法):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | for i in range(len(JSON_data["results"])): try: print"ListingID=" + JSON_data["results"][i]["listingId"] except KeyError: print"ListingID is unknown" try: print"Address=" + JSON_data["results"][i]["address"] except KeyError: print"Address is unknown" try: print"landsize=" + JSON_data["results"][i]["landsize"] except KeyError: print"landsize is unknown" try: print"state =" + JSON_data["results"][i]["state"] except KeyError: print"state is unknown" |
感谢您的建议!
您可以使用
1 | listing_id = JSON_data["results"][i].get("listingId") |
返回
1 2 | if 'listingId' in JSON_data["results"][i]: # the key is present, do something with the value |
接下来,您不想在这里使用
1 2 3 | for nesteddict in JSON_data["results"]: if 'listingId' in nesteddict: listing_id = nesteddict['nesteddict'] |
接下来,不要硬编码您检查的所有键,而是在键列表上使用循环:
1 2 3 4 5 6 7 8 9 | expected_keys = ['listingId', 'address', 'landsize', ...] for nesteddict in JSON_data["results"]: for key in expected_keys: if key not in nesteddict: print(key, 'is unknown') else: value = nesteddict[key] print('{} = {}'.format(key, value) |
如果您不需要打印缺少某个键,那么您也可以使用字典视图,它作为集合。设置支持交集操作,因此可以要求在预期键和可用键之间进行交集:
1 2 3 4 5 6 7 8 | # note, using a set here now expected_keys = {'listingId', 'address', 'landsize', ...} for nesteddict in JSON_data["results"]: for key in nesteddict.keys() & expected_keys: # get the intersection # each key is guaranteed to be in nesteddict value = nesteddict[key] print('{} = {}'.format( |
这个
您也可以循环使用键名-这意味着您只有1个try/except。因为它在一个循环中,所以它对每个键重复相同的代码,并在每个循环中更改键名。
1 2 3 4 5 6 | for i in range(len(JSON_data["results"])): for key in ('listingId', 'address', 'landsize', 'state'): try: print '{}: {}'.format(key, JSON_data["results"][i][key]) except KeyError: print '{} is unknown'.format(key) |
如果我没有弄错,您还可以通过直接迭代结果使代码更清晰:
1 2 | for result in JSON_data['results']: ... |
在你写
注意:您提到的实际数据比这要复杂得多。如果有许多键名,那么从外部(或者至少在其他地方)存储键名可能是有意义的。您可以创建一个密钥名文件,并通过执行以下操作创建一个名称列表…
1 2 | with open('key_names.txt', 'r') as f: key_names = [line.strip() for line in f] |
下面是我将用于迭代JSON对象并列出我想要的值的方法。另外,请确保您的JSON对象在发布到这里之前格式正确。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | import json def import_data(): data =""" { "results": [ { "listingId":"1", "address":"123 Main st", "landsize":"190 m2" }, { "listingId":"2", "address":"345 North st", "state":"California" } ] } """ return data def format_Data(): data = import_data() data = json.loads(data) array = [] print data for data_item in data['results']: for key, value in data_item.items(): if key == 'listingId': listingId = value print ('ListingID= {}').format(listingId) elif key == 'address': address = value print ('Address= {}').format(address) elif key == 'landsize': landsize = value print ('Landsize= {}').format(landsize) elif key == 'state': state = value print ('State= {}').format(state) |
输出:
1 2 3 4 5 6 7 | {u'results': [{u'landsize': u'190 m2', u'listingId': u'1', u'address': u'123 Main st'}, {u'state': u'California', u'listingId': u'2', u'address': u'345 North st'}]} Landsize= 190 m2 ListingID= 1 Address= 123 Main st State= California ListingID= 2 Address= 345 North s |
T