我正在从返回JSON的REST API解析数据,我对这个特定的结构有点问题:
{ 'Order' : [
{ 'orderID': '1',
'OrderLines': {
'OrderLine': [
{ 'lineID':'00001', 'quantity':'1', 'cost':'10', 'description':'foo' },
{ 'lineID':'00002', 'quantity':'2', 'cost':'23.42', 'description':'bar' }
]}
}
{ 'orderID': '2',
'OrderLines': {
'OrderLine':
{ 'lineID':'00003', 'quantity':'6', 'cost':'12.99', 'description':'lonely' }
}
}
]}
如果您注意到,第二个订单只有一个OrderLine
,那么它不会返回包含字典的列表,而是返回字典。这是我想要做的:
orders_json = json.loads(from_server)
for order in orders_json['Order']:
print 'Order ID: {}'.format(order['orderID'])
for line in order['OrderLines']['OrderLine']:
print '-> Line ID: {}, Quantity: {}'.format(line['lineID'], line['quantity'])
它适用于第一个订单,但是第二个订单抛出TypeError: string indices must be integers
,因为line
现在是包含字典的字符串,而不是列表中的字典。我几个小时以来一直在反对这个问题,我觉得我错过了一些明显的东西。
以下是我尝试过的一些事情:
len(line)
查看它是否为我提供了一行唯一的订单。它不是。它返回字典中key:value对的数量,在我的真实程序中为10,包含10行的订单也将返回。答案 0 :(得分:3)
设计该API的人并没有做得非常出色。无论如何,您可以检查OrderLine
是否是列表,如果不是,请在进行任何处理之前将其包装在单元素列表中:
if not isinstance(order_line, list):
order_line = [order_line]
这样可行,我个人的偏好是修复API。
答案 1 :(得分:1)
我会检查类型是否正确,然后在必要时将其转换为列表以进行统一访问:
lines = order['OrderLines']['OrderLine']
lines = [lines] if not isinstance(lines, list) else lines
for line in lines:
...
答案 2 :(得分:0)
您可以检查您尝试访问的对象的类型:
# ...
print 'Order ID: {0}'.format(order['orderID'])
lines = order['OrderLines']['OrderLine']
if isinstance(lines, list):
for line in lines:
print line['lineID']
elif isinstance(lines, dict):
print lines['lineID']
else:
raise ValueError('Illegal JSON object')
修改:根据@NPE的建议,将dict
包裹在list
中是更好,更智能的解决方案。