Python项目:从Ekahau JSON文件提取AP信息的实现疑问
从Ekahau导出的JSON中提取AP信息的最优方案
需求与JSON结构
首个Python项目需从Ekahau导出的JSON文件中提取无线AP信息,目标是生成如下格式的嵌套字典用于后续计算与导出:
accessPoints = { 'AP001': {'floorPlanId':'', 'name':'Measured-AP-02:f5', 'mine':'true'}, 'AP002': {'floorPlanId':'Warehouse', 'name':'Measured-AP-cc:f8', 'mine':'true'} }
Ekahau导出的JSON结构示例:
{ "accessPoints": [ { "location": { "floorPlanId": "0f422470-9c8f-41d7-a51f-a19dcd1208cc", "coord": { "x": 815.4422419685577, "y": 636.5659603554341 } }, "name": "WarehouseAP-4", "mine": true, "hidden": false, "userDefinedPosition": true, "noteIds": [], "vendor": "Aruba", "model": "AP-574 + ANT-2x2-2314 + ANT-4x4-5314", "tags": [], "id": "f27feef1-3800-4853-a0fe-21bc1da00d2f", "status": "CREATED" }, { "location": { "floorPlanId": "0f422470-9c8f-41d7-a51f-a19dcd1208cc", "coord": { "x": 2710.3321941216677, "y": 981.6322624743677 } }, "name": "WarehouseAP-3", "mine": true, "hidden": false, "userDefinedPosition": true, "noteIds": [], "vendor": "Aruba", "model": "AP-574 + ANT-2x2-2314 + ANT-4x4-5314", "tags": [], "id": "535d8800-b264-4737-a4ba-1c69c518ad06", "status": "CREATED" } ] }
最初尝试的问题
最初采用逐行读取、冒号分割键值对的方式,代码如下:
for file_name in all_json_files: # loop for all json files if file_name.endswith(extension): category = file_name[:-5] json_file_path = temp_files + '/' + file_name open_file = open(json_file_path, 'r') skip_lines = 2 # amount of lines to skip current_line = 0 # reset current_line in each file list_of_keys = [] # leere list_of_keys für jede neue category/file list_of_values = [] for lines in open_file: # loop for each line in the json file lines.strip('{') lines.strip('}') if current_line >= skip_lines and len(lines.split(':')) > 1: line_content = lines.split(':') key = line_content[0].strip() value = line_content[1].strip() value = value[:-1] # remove comma at end of line if key not in list_of_keys and value != '': list_of_keys.append(key) if value not in list_of_values: list_of_values.append(value) # for key, value in zip(list_of_keys, list_of_values): # create database # database[key] = value current_line += 1 open_file.close()
这种方式无法处理嵌套结构(比如location下的floorPlanId),也无法将每个AP的信息存入独立子字典,容错性极低(比如JSON格式换行、逗号位置变化都会导致解析失败)。
现有方案的合理性与优化
改用json.load()是最优选择,因为Python标准库的json模块专门用于解析结构化JSON数据,能自动处理嵌套结构、数据类型转换(比如布尔值true转为Python的True),且代码简洁、容错性高。
改进后的完整代码
在现有代码基础上,添加逻辑将解析后的JSON转换为目标格式的嵌套字典:
import json extension = '.json' # 定义需要提取的字段,可根据需求修改,支持嵌套路径 FIELDS_TO_EXTRACT = [ ('floorPlanId', 'location.floorPlanId'), ('name', 'name'), ('mine', 'mine') ] def get_nested_value(data, path): """从嵌套字典中根据路径提取值""" keys = path.split('.') current = data for key in keys: if key not in current: return '' current = current[key] # 转换布尔值为字符串(如果需要) return str(current).lower() if isinstance(current, bool) else current for file_name in all_json_files: if file_name.endswith(extension): json_file_path = f"{temp_files}/{file_name}" with open(json_file_path, 'r') as file: data = json.load(file) # 生成目标格式的嵌套字典 access_points = {} for idx, ap in enumerate(data.get('accessPoints', []), start=1): ap_key = f"AP{idx:03d}" # 生成AP001、AP002格式的键 ap_info = {} for field_name, path in FIELDS_TO_EXTRACT: ap_info[field_name] = get_nested_value(ap, path) access_points[ap_key] = ap_info # 后续可对access_points进行导出或计算操作 print(access_points)
通用性说明
- 通过
FIELDS_TO_EXTRACT列表可灵活配置需要提取的字段,新增或修改字段无需修改核心循环逻辑 get_nested_value函数支持任意深度的嵌套字段提取,适配同类结构的JSON文件- 自动处理布尔值转换(如果不需要可删除对应逻辑)
- 用
data.get('accessPoints', [])避免JSON中无accessPoints字段时抛出异常
其他可选方案
如果需要更复杂的JSON查询(比如过滤特定条件的AP),可以考虑使用第三方库jsonpath-ng,安装后可通过类似XPath的语法提取数据:
# 需先安装:pip install jsonpath-ng from jsonpath_ng import parse # 示例:提取所有Aruba品牌的AP名称 jsonpath_expr = parse('$..accessPoints[?(@.vendor == "Aruba")].name') matches = [match.value for match in jsonpath_expr.find(data)]
但对于当前需求,标准库的json模块已足够,无需额外依赖。
内容的提问来源于stack exchange,提问作者Ianus
相关产品推荐
相关产品推荐

