我有一个最佳实践问题,涉及使用try / except语句遍历Python中的JSON文件。
我有一个看起来像这样的JSON文件(此问题大大简化了):
"results": [
{
"listingId":"1"
"address":"123 Main st"
"landsize":"190 m2"
},
{
"listingId":"2"
"address":"345 North st"
"state":"California"
}
]
正如我所说,这是超级简化的(在我的实际问题中,我感兴趣的大约有30个键值对,并且有成千上万条记录)面临的挑战是,即使键非常一致(始终存在)相同的30),偶尔会有缺失的键/值对。
如果缺少一两个或10个,我希望将其余记录写出,所以目前的方法是对每个键值对使用try / catch语句,这似乎使我很惊讶一种非常低效的检查方法,我相信还有更好的方法。
我的代码看起来像这样(我确信这不是执行此操作的最佳方法):
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"
任何建议表示赞赏!
答案 0 :(得分:2)
您可以使用dict.get()
method避免捕获异常:
listing_id = JSON_data["results"][i].get("listingId")
返回None
或其他默认值,作为第二个参数传入。您还可以检查密钥是否先出现:
if 'listingId' in JSON_data["results"][i]:
# the key is present, do something with the value
接下来,您要在此处不使用range()
。您最好直接在results
列表上循环,因此每次都可以直接引用字典而无需使用完整的JSON_data["results"][i]
前缀:
for nesteddict in JSON_data["results"]:
if 'listingId' in nesteddict:
listing_id = nesteddict['nesteddict']
接下来,而不是对您检查的所有键进行硬编码,请在键列表上使用循环:
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)
如果不需要打印缺少的键,则还可以使用dictionary views,它是一组键。设置支持交集操作,因此您可以要求您期望的键和可用键之间的交集:
# 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(
此for
循环仅处理nesteddict
中的和expected_keys
中的键,仅此而已。
答案 1 :(得分:1)
您也可以遍历键名-这意味着您只有1个try / except。由于它是循环的,因此它会为每个键重复相同的代码,并在每个循环中更改键名称。
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)
如果我没记错的话,您还可以通过直接遍历结果来使代码更简洁:
for result in JSON_data['results']:
...
在编写JSON_data['results'][i]
的地方,将其更改为简单的result
。
注意:您提到的实际数据要比这复杂得多。如果密钥名称很多,则可以在外部(或至少在其他位置)存储密钥名称。您可以通过执行以下操作来创建键名称文件并创建名称列表:
with open('key_names.txt', 'r') as f:
key_names = [line.strip() for line in f]
答案 2 :(得分:0)
这是我用于遍历json对象并列出所需值的方法。另外,在发布到这里之前,请确保您正确设置了json对象的格式。
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)
输出:
{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