前情提要
在一个项目开发中需要后端解析并分析数据得出结果报告,一开始用的Java后端,后面一堆Json数据解析的实在头疼,于是捡起老胶水:Python 辅助开发作为后端的核心算法部分服务接口
Java:SpringBoot 结合 RestTemplate 调用服务接口
后端解析完数据通过RestTemplate发送http请求
Python:如何解析到手的嵌套Json数据
这一串又臭又长的Json数据结构是这样的:数组元素是Json对象,对象中又有元素项是数组,数组中管理的又有是对象的存在。简述就是数组对象俄罗斯套娃,需求又是拿到里面的一两个元素项下的值,下面是一小段数据例子
[{'desc': 'https://special-item-501508.framer.app/', 'deviceGroupId': 1, 'envAttr': {'browser': {'displayName': 'Browser', 'order': '11', 'value': 'Chrome'}, 'city': {'displayName': 'City', 'order': '4', 'value': 'Tucheng'}, 'country': {'displayName': 'Country or Region', 'order': '2', 'value': 'China'}, 'deviceType': {'displayName': 'Device Type', 'order': '18', 'value': 'PC'}, 'displayHeight': {'displayName': 'Screen Height', 'order': '13', 'value': 2234}, 'displayWidth': {'displayName': 'Screen Width', 'order': '12', 'value': 3456}, 'ip': {'displayName': 'IP', 'order': '1', 'value': '103.156.242.195'}, 'operatingSystem': {'displayName': 'OS', 'order': '9', 'value': 'Mac'}, 'province': {'displayName': 'Province', 'order': '3', 'value': 'Taipei'}, ..... 'pageAttr': {'clientCreateTs': {'displayName': '', 'value': 1701427202179}, 'libVersion': {'displayName': 'SDK Version', 'order': '22', 'value': '1.4.0'}, 'referrer': {'displayName': 'Previous URL', 'order': '15', 'value': 'https://framer.com/'}, 'referrerHost': {'displayName': 'Previous Domain', 'order': '16', 'value': 'framer.com'}, 'sdkType': {'displayName': 'SDK Type', 'order': '21', 'value': 'WEB'}, 'sessionId': {'displayName': '', 'order': '', 'value': 877}, 'title': {'displayName': 'Page Title', 'order': '10', 'value': 'SaaS Template'}, 'uri': {'displayName': 'Page URI', 'order': '12', 'value': 'https://special-item-501508.framer.app/'}, 'url': {'displayName': 'Page URL', 'order': '11', 'value': 'https://special-item-501508.framer.app/'}, 'urlHost': {'displayName': 'Page Domain', 'order': '13', 'value': 'special-item-501508.framer.app'}, 'urlPath': {'displayName': 'Page Path', 'order': '14', 'value': '/'}}, ...}
这一段给Java解析想想我都头疼,这时候就想起了这门“很随便”的语言:Python。解析数据的代码如下
@app.route('/reslove_json', methods=['POST'])
def reslove_json():data = request.jsonprint(data)if data:# 遍历data数组for item in data:print(f"'desc': {item['desc']}")# 如果数组元素中存在'envAttr'if 'envAttr' in item:envAttr = item['envAttr']print(f"'browser': {envAttr.get('browser')}")return jsonify({'code': '200', 'msg': '请求成功!', 'data': 'succeed'})
运行结果如下
拓展
如果Json数据对象格式不统一,又该怎么办呢?下面代码给出示例:
data = [ { "id": 1, "obj": { "name": "John Doe", "age": 30 } }, { "id": 2, "details": { "name": "Jane Doe", "age": 25 } }
] # 使用列表推导来获取所有的'name'值
names = [item['obj'].get('name', None) if 'obj' in item else item['details'].get('name', None) for item in data] # 上面列表推导式等同于以下代码
for item in data:if 'obj' in item:name = item['obj'].get('name', None);elsename = item['details'].get('name', None);print(names)
遍历data
列表中的每个字典对象。对于每个对象,我们检查它是否包含obj
键,如果包含,我们就从obj
字典中获取name
的值;如果不包含obj
键但包含details
键,我们就从details
字典中获取name
的值。如果name
键不存在于任何子字典中,get
方法将返回None
。
用列表推导式的一个优点是相比于for循环更高效,因为列表推导式在执行时调用的是Python的底层C代码,而for循环则是用Python代码来执行。