如何正确解析简单json的JSON?
我可以有以下的JSON字符串:
{ "response" : [ [ { "name" : "LA_",
"uid" : 123456
} ],
[ { "cid" : "1",
"name" : "Something"
} ],
[ { "cid" : 1,
"name" : "Something-else"
} ]
] }
或者以下其中之一:
{"error":"some-error"}
{ "response" : [ [ { "name" : "LA_",
"uid" : 123456
} ],
[ { "cid" : "1",
"name" : ""
} ],
[ { "cid" : 1,
"name" : "Something-else"
} ]
] }
{ "response" : [ [ { "name" : "LA_",
"uid" : 123456
} ] ] }
所以,我不确定所有的子元素和内容是否都在里面。要获取Something
的值,做以下检查是否足够:
if jsonstr.get('response'):
jsonstr = jsonstr.get('response')[1][0]
if jsonstr:
name = jsonstr.get('name')
if jsonstr: # I don't need empty value
# save in the database
这个过程可以简化吗?
1 个回答
2
你不能保证每次解析你的内部对象时,它们的顺序都是一样的,所以用索引来引用属性为 name
且值为 Something
的对象并不安全。
与其嵌套一堆 if
语句,不如使用一种叫做 列表推导式 的方法。注意,如果你遍历 response
这个键,你会得到一个包含多个列表的列表,每个列表里面都有一个字典:
>>> data = {"response":[[{"uid":123456,"name":"LA_"}],[{"cid":"1","name":"Something"}],[{"cid":1,"name":"Something-else"}]]}
>>> [lst for lst in data.get('response')]
[[{'name': 'LA_', 'uid': 123456}], [{'name': 'Something', 'cid': '1'}], [{'name': 'Something-else', 'cid': 1}]]
如果你取每个列表中的第一个项目(lst[0]
),你就会得到一个对象的列表:
>>> [lst[0] for lst in data.get('response')]
[{'name': 'LA_', 'uid': 123456}, {'name': 'Something', 'cid': '1'}, {'name': 'Something-else', 'cid': 1}]
接着,如果你在列表推导式中添加一个 if
条件来匹配对象的 name
属性,你就会得到一个只包含你想要的对象的列表:
>>> [lst[0] for lst in data.get('response') if lst[0].get('name') == 'Something']
[{'name': 'Something', 'cid': '1'}]
然后通过索引这个最终列表中的第一个项目,你就能得到你想要的对象:
>>> [lst[0] for lst in data.get('response') if lst[0].get('name') == 'Something'][0]
{'name': 'Something', 'cid': '1'}
这样你就可以把这个过程变成一个函数,继续你的工作:
def get_obj_by_name(data, name):
objects = [lst[0] for lst in data.get('response', []) if lst[0].get('name') == name]
if objects:
return objects[0]
return None
print get_obj_by_name(data, 'Something')
# => {'name': 'Something', 'cid': '1'}
print get_obj_by_name(data, 'Something')['name']
# => 'Something'
而且这个函数应该很健壮,如果找不到 response
这个键,它会返回 None
:
print get_obj_by_name({"error":"some-error"}, 'Something')
# => None