105 lines
3.5 KiB
Python
105 lines
3.5 KiB
Python
|
#!/usr/bin/env python
|
|||
|
# -*- coding: utf-8 -*-
|
|||
|
|
|||
|
"""
|
|||
|
通用JSON/字典解析工具
|
|||
|
"""
|
|||
|
|
|||
|
import json
|
|||
|
from typing import Any, Dict, Optional
|
|||
|
from utils.logger import get_logger
|
|||
|
|
|||
|
logger = get_logger("json_parser")
|
|||
|
|
|||
|
|
|||
|
def safe_parse_json(param: str, script_id: Optional[str] = None, default_return: Any = None) -> Any:
|
|||
|
"""安全解析JSON或Python字典格式的字符串
|
|||
|
|
|||
|
尝试多种解析方式:
|
|||
|
1. 首先尝试标准JSON解析
|
|||
|
2. 如果JSON解析失败,尝试使用eval解析Python字典格式
|
|||
|
|
|||
|
Args:
|
|||
|
param: 要解析的字符串
|
|||
|
script_id: 脚本ID,用于日志记录
|
|||
|
default_return: 解析失败时的默认返回值
|
|||
|
|
|||
|
Returns:
|
|||
|
解析后的数据,失败时返回default_return
|
|||
|
"""
|
|||
|
if not isinstance(param, str):
|
|||
|
if script_id:
|
|||
|
logger.error(f"脚本 {script_id} 输入参数不是字符串类型: {type(param)}")
|
|||
|
else:
|
|||
|
logger.error(f"输入参数不是字符串类型: {type(param)}")
|
|||
|
return default_return
|
|||
|
|
|||
|
# 1. 首先尝试标准JSON解析
|
|||
|
try:
|
|||
|
data = json.loads(param)
|
|||
|
return data
|
|||
|
except json.JSONDecodeError:
|
|||
|
# 2. 如果JSON解析失败,尝试使用eval解析Python字典或列表格式
|
|||
|
try:
|
|||
|
# 安全地使用eval解析字典或列表字符串
|
|||
|
stripped_param = param.strip()
|
|||
|
if (stripped_param.startswith('{') and stripped_param.endswith('}')) or \
|
|||
|
(stripped_param.startswith('[') and stripped_param.endswith(']')):
|
|||
|
data = eval(param, {"__builtins__": {}}, {})
|
|||
|
return data
|
|||
|
else:
|
|||
|
if script_id:
|
|||
|
logger.error(f"脚本 {script_id} 参数格式不正确: {param}")
|
|||
|
else:
|
|||
|
logger.error(f"参数格式不正确: {param}")
|
|||
|
return default_return
|
|||
|
except Exception as eval_error:
|
|||
|
if script_id:
|
|||
|
logger.error(f"脚本 {script_id} 参数解析失败: {str(eval_error)}, 参数: {param}")
|
|||
|
else:
|
|||
|
logger.error(f"参数解析失败: {str(eval_error)}, 参数: {param}")
|
|||
|
return default_return
|
|||
|
|
|||
|
|
|||
|
def safe_parse_dict(param: str, script_id: Optional[str] = None) -> Optional[Dict[str, Any]]:
|
|||
|
"""安全解析为字典类型
|
|||
|
|
|||
|
Args:
|
|||
|
param: 要解析的字符串
|
|||
|
script_id: 脚本ID,用于日志记录
|
|||
|
|
|||
|
Returns:
|
|||
|
解析后的字典,失败时返回None
|
|||
|
"""
|
|||
|
data = safe_parse_json(param, script_id, None)
|
|||
|
|
|||
|
if not isinstance(data, dict):
|
|||
|
if script_id:
|
|||
|
logger.error(f"脚本 {script_id} 参数格式错误,期望字典类型: {type(data)}")
|
|||
|
else:
|
|||
|
logger.error(f"参数格式错误,期望字典类型: {type(data)}")
|
|||
|
return None
|
|||
|
|
|||
|
return data
|
|||
|
|
|||
|
|
|||
|
def safe_parse_list(param: str, script_id: Optional[str] = None) -> Optional[list]:
|
|||
|
"""安全解析为列表类型
|
|||
|
|
|||
|
Args:
|
|||
|
param: 要解析的字符串
|
|||
|
script_id: 脚本ID,用于日志记录
|
|||
|
|
|||
|
Returns:
|
|||
|
解析后的列表,失败时返回None
|
|||
|
"""
|
|||
|
data = safe_parse_json(param, script_id, None)
|
|||
|
|
|||
|
if not isinstance(data, list):
|
|||
|
if script_id:
|
|||
|
logger.error(f"脚本 {script_id} 参数格式错误,期望列表类型: {type(data)}")
|
|||
|
else:
|
|||
|
logger.error(f"参数格式错误,期望列表类型: {type(data)}")
|
|||
|
return None
|
|||
|
|
|||
|
return data
|