含非ASCII字符的JSON字符串无法用json.loads解析的问题求助
解决JSON解析失败(控制字符导致)的方案
问题根源
核心问题是JSON字符串里混入了JSON规范不允许的不可见控制字符(比如ASCII 0-31范围内,除了\t、\n、\r之外的字符,像垂直制表符、换页符这类),肉眼手动看不到,但会直接触发JSONDecodeError,也会导致jsonlint验证异常。
具体解决步骤
1. 定位问题字符
先找出到底是哪些控制字符在搞鬼:
raw_json_str = "你的原始JSON字符串" # 替换成你从网页拿到的内容 for idx, char in enumerate(raw_json_str): ord_char = ord(char) # 排查除了制表、换行、回车之外的控制字符 if ord_char < 32 and char not in '\t\n\r': print(f"问题字符位置 {idx}: ASCII编码 {ord_char},字符详情: {repr(char)}")
也可以用文本编辑器的「显示控制字符」功能(比如VS Code开启后,这类字符会显示为灰色特殊标记)直接查看。
2. 清理控制字符
根据情况选择以下方案:
- 方案一:精准清理非法控制字符(保留合法的\t、\n、\r)
import re import json raw_json_str = "你的原始JSON字符串" # 匹配并移除所有JSON不允许的控制字符 cleaned_str = re.sub(r'[\x00-\x08\x0B\x0C\x0E-\x1F]', '', raw_json_str) # 测试解析 try: parsed_data = json.loads(cleaned_str) print("解析成功!") except json.JSONDecodeError as e: print(f"还有残留问题: {e}")
- 方案二:简单替换所有无效控制字符(如果HTML内容里的控制字符无实际意义)
cleaned_str = ''.join([c if ord(c) >= 32 or c in '\t\n\r' else ' ' for c in raw_json_str])
3. 验证结果
清理后直接用json.loads测试,或者用本地的jsonlint工具验证,确认解析正常。
4. 后续预防
爬取网页时,提前处理响应内容避免问题:
import requests import re import json response = requests.get("目标网页URL") # 解码时替换无效字符,再提取JSON内容 content = response.content.decode('utf-8', errors='replace') # 先清理控制字符再解析 cleaned_content = re.sub(r'[\x00-\x08\x0B\x0C\x0E-\x1F]', '', content) data = json.loads(cleaned_content)
内容的提问来源于stack exchange,提问作者Akshay Hazari
相关产品推荐
相关产品推荐

