方法1:使用标准库json.loads()捕获异常(最常用)
python
import json
def validate_json(json_str):
"""
验证JSON字符串格式是否正确
"""
try:
json.loads(json_str)
return True, None
except json.JSONDecodeError as e:
return False, e
# 使用示例
test_cases = [
'{"name": "张三", "age": 25}', # 正确
'{"name": "张三", "age": 25', # 缺少右括号
"{'name': '张三'}", # 单引号错误
'{"name": "张三", "age": }', # 缺少值
]
for i, json_str in enumerate(test_cases):
is_valid, error = validate_json(json_str)
print(f"\n测试 {i+1}: {repr(json_str[:50])}")
if is_valid:
print("✓ JSON格式正确")
else:
print(f"✗ JSON格式错误: {error.msg}")
print(f" 位置: 第{error.lineno}行, 第{error.colno}列")
print(f" 上下文: {repr(error.doc[max(0, error.pos-20):error.pos+20])}")
方法2:详细的JSON错误诊断工具
python
import json
import re
class JSONValidator:
"""JSON格式验证器,提供详细错误信息"""
@staticmethod
def validate(json_str, verbose=True):
"""
验证JSON并返回详细信息
"""
errors = []
# 检查1: 是否为空
if not json_str or not json_str.strip():
errors.append("JSON字符串为空")
return False, errors
# 检查2: 尝试解析
try:
data = json.loads(json_str)
return True, ["JSON格式正确"]
except json.JSONDecodeError as e:
errors.append(f"解析错误: {e.msg}")
errors.append(f"位置: 行{e.lineno}, 列{e.colno}")
errors.append(f"字符位置: {e.pos}")
# 显示错误上下文
context_start = max(0, e.pos - 30)
context_end = min(len(json_str), e.pos + 30)
context = json_str[context_start:context_end]
errors.append(f"上下文: ...{context}...")
# 标记错误位置
marker = ' ' * (e.pos - context_start) + '^'
errors.append(f"标记: {marker}")
# 检查3: 常见格式问题
if "'" in json_str and '"' not in json_str:
errors.append("警告: 检测到单引号,JSON应使用双引号")
if json_str.startswith("'") or json_str.startswith('"'):
# 检查是否有BOM标记
if json_str.startswith('\ufeff'):
errors.append("警告: 检测到BOM标记")
# 检查4: 括号匹配
bracket_stack = []
for i, char in enumerate(json_str):
if char in '{[(':
bracket_stack.append((char, i))
elif char in '}])':
if not bracket_stack:
errors.append(f"错误: 位置{i}处有未匹配的闭合括号'{char}'")
break
opening, pos = bracket_stack.pop()
if (opening == '{' and char != '}') or \
(opening == '[' and char != ']') or \
(opening == '(' and char != ')'):
errors.append(f"错误: 位置{pos}的'{opening}'与位置{i}的'{char}'不匹配")
if bracket_stack:
for opening, pos in bracket_stack:
errors.append(f"错误: 位置{pos}的'{opening}'没有闭合")
return False, errors
@staticmethod
def pretty_print_errors(json_str):
"""
美观地打印JSON错误信息
"""
is_valid, errors = JSONValidator.validate(json_str)
print("=" * 60)
print("JSON格式检查结果")
print("=" * 60)
print(f"输入: {repr(json_str[:100])}")
print(f"状态: {'✓ 通过' if is_valid else '✗ 失败'}")
print("-" * 60)
for error in errors:
print(f" {error}")
print("=" * 60)
return is_valid
# 使用示例
if __name__ == "__main__":
# 测试各种错误情况
test_json = """
{"name": "张三", "age": 25, "city": "北京" # 缺少右括号
"""
JSONValidator.pretty_print_errors(test_json)
print("\n" + "=" * 60)
print("测试正确的JSON")
print("=" * 60)
correct_json = '{"name": "张三", "age": 25, "city": "北京"}'
JSONValidator.pretty_print_errors(correct_json)
方法3:逐行验证大JSON文件
python
import json
def validate_json_file(filepath):
"""
验证JSON文件格式
"""
try:
with open(filepath, 'r', encoding='utf-8') as f:
content = f.read()
json.loads(content)
print(f"✓ {filepath} 格式正确")
return True
except json.JSONDecodeError as e:
print(f"✗ {filepath} 格式错误:")
print(f" 错误: {e.msg}")
print(f" 位置: 行{e.lineno}, 列{e.colno}")
# 显示错误行
with open(filepath, 'r', encoding='utf-8') as f:
lines = f.readlines()
if e.lineno <= len(lines):
print(f" 错误行: {e.lineno}: {lines[e.lineno-1].rstrip()}")
# 标记错误位置
marker = ' ' * (e.colno - 1) + '^'
print(f" {marker}")
return False
except FileNotFoundError:
print(f"✗ 文件不存在: {filepath}")
return False
# 使用示例
# validate_json_file('data.json')
方法4:使用jsonschema验证JSON结构
python
import json
from jsonschema import validate, ValidationError, SchemaError
def validate_json_structure(json_str, schema=None):
"""
验证JSON结构是否符合预期
"""
try:
data = json.loads(json_str)
except json.JSONDecodeError as e:
return False, f"JSON格式错误: {e.msg}"
# 如果提供了schema,验证结构
if schema:
try:
validate(instance=data, schema=schema)
return True, "JSON结构正确"
except ValidationError as e:
return False, f"结构验证失败: {e.message}"
except SchemaError as e:
return False, f"Schema错误: {e.message}"
return True, "JSON格式正确"
# 使用示例
schema = {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "number"},
"email": {"type": "string", "format": "email"}
},
"required": ["name", "age"]
}
json_str = '{"name": "张三", "age": 25, "email": "zhangsan@example.com"}'
is_valid, message = validate_json_structure(json_str, schema)
print(f"{message}: {is_valid}")
方法5:命令行工具方式
python
# 保存为 validate_json.py
import json
import sys
import argparse
def main():
parser = argparse.ArgumentParser(description='JSON格式验证工具')
parser.add_argument('file', nargs='?', help='JSON文件路径')
parser.add_argument('-s', '--string', help='JSON字符串')
parser.add_argument('-v', '--verbose', action='store_true', help='详细输出')
args = parser.parse_args()
# 从文件或字符串读取
if args.file:
with open(args.file, 'r', encoding='utf-8') as f:
json_str = f.read()
source = f"文件: {args.file}"
elif args.string:
json_str = args.string
source = "字符串"
else:
# 从stdin读取
json_str = sys.stdin.read()
source = "标准输入"
# 验证
try:
data = json.loads(json_str)
print(f"✓ {source}: JSON格式正确")
if args.verbose:
print(f" 类型: {type(data)}")
if isinstance(data, dict):
print(f" 键数量: {len(data)}")
elif isinstance(data, list):
print(f" 元素数量: {len(data)}")
sys.exit(0)
except json.JSONDecodeError as e:
print(f"✗ {source}: JSON格式错误", file=sys.stderr)
print(f" 错误: {e.msg}", file=sys.stderr)
print(f" 位置: 行{e.lineno}, 列{e.colno}", file=sys.stderr)
if args.verbose:
# 显示上下文
lines = json_str.split('\n')
if e.lineno <= len(lines):
print(f"\n 错误行 {e.lineno}:", file=sys.stderr)
print(f" {lines[e.lineno-1]}", file=sys.stderr)
marker = ' ' * (e.colno - 1) + '^'
print(f" {marker}", file=sys.stderr)
sys.exit(1)
if __name__ == '__main__':
main()
使用方式:
bash
# 验证文件
python validate_json.py data.json
# 验证字符串
python validate_json.py -s '{"name": "test"}'
# 详细模式
python validate_json.py -v data.json
# 从管道读取
echo '{"name": "test"}' | python validate_json.py
方法6:在线验证和格式化工具
如果不想写代码,可以使用这些工具:
- JSONLint: https://jsonlint.com/
- JSON Formatter: https://jsonformatter.curiousconcept.com/
- VS Code插件: JSON相关插件
方法7:使用IDE内置功能
VS Code:
- 安装 "JSON" 相关扩展
.json文件自动验证- 快捷键:
Ctrl+Space提示
PyCharm:
- 内置JSON验证
- 自动格式化:
Ctrl+Alt+L - 语法高亮显示错误
实用调试技巧
python
import json
import traceback
def debug_json_error(json_str):
"""
调试JSON错误的实用函数
"""
print("=" * 70)
print("JSON调试信息")
print("=" * 70)
print(f"长度: {len(json_str)} 字符")
print(f"前100字符: {repr(json_str[:100])}")
print(f"后100字符: {repr(json_str[-100:])}")
# 检查常见问题
checks = [
("是否为空", lambda s: not s.strip()),
("是否以单引号开头", lambda s: s.strip().startswith("'")),
("是否包含单引号", lambda s: "'" in s and '"' not in s),
("是否有BOM标记", lambda s: s.startswith('\ufeff')),
("括号是否匹配", lambda s: s.count('{') != s.count('}') or s.count('[') != s.count(']')),
]
print("\n初步检查:")
for check_name, check_func in checks:
result = check_func(json_str)
status = "⚠ 可能有问题" if result else "✓ 正常"
print(f" {check_name}: {status}")
# 尝试解析
print("\n解析尝试:")
try:
data = json.loads(json_str)
print(f"✓ 解析成功!")
print(f" 类型: {type(data)}")
if isinstance(data, dict):
print(f" 键: {list(data.keys())[:5]}")
return True
except json.JSONDecodeError as e:
print(f"✗ 解析失败!")
print(f" 错误信息: {e.msg}")
print(f" 位置: 行{e.lineno}, 列{e.colno}")
# 显示详细上下文
print(f"\n 错误位置上下文:")
start = max(0, e.pos - 50)
end = min(len(json_str), e.pos + 50)
context = json_str[start:end]
print(f" ...{context}...")
# 标记位置
marker_pos = e.pos - start
marker = ' ' * marker_pos + '^'
print(f" {' ' * (marker_pos)}{marker}")
# 显示周围几行
print(f"\n 周围行:")
lines = json_str.split('\n')
for i in range(max(0, e.lineno-2), min(len(lines), e.lineno+2)):
prefix = " > " if i == e.lineno-1 else " "
print(f" {prefix}行{i+1}: {repr(lines[i][:100])}")
return False
finally:
print("=" * 70)
# 使用示例
if __name__ == "__main__":
# 测试有问题的JSON
bad_json = '''
{
"name": "张三",
'age': 25, # 这里用了单引号
"city": "北京"
}
'''
debug_json_error(bad_json)
推荐方案总结
对于您的股票数据场景,建议使用:
python
import json
import logging
# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def safe_json_parse(data_str, source="未知来源"):
"""
安全解析JSON,提供详细错误信息
"""
try:
return json.loads(data_str)
except json.JSONDecodeError as e:
logger.error(f"JSON解析失败 [{source}]:")
logger.error(f" 错误: {e.msg}")
logger.error(f" 位置: 行{e.lineno}, 列{e.colno}")
logger.error(f" 上下文: {repr(data_str[max(0, e.pos-30):e.pos+30])}")
# 尝试修复建议
if "'" in data_str and '"' not in data_str:
logger.warning(" 建议: 检测到单引号,尝试使用 ast.literal_eval 或替换为双引号")
raise
# 在您的代码中使用
try:
data_dict = safe_json_parse(data_str, "Redis")
# 处理数据...
except json.JSONDecodeError:
# 记录错误并跳过或使用默认值
logger.error("跳过无效数据")
continue
这样可以快速定位和修复JSON格式问题!