pandas.json_normalize是展开单层嵌套字段最直接稳定的方法,能自动将字典拆为多列并支持路径定位,优于手写apply(pd.Series),但需先确保输入为Python字典对象而非JSON字符串。

用 pandas.json_normalize 展开单层嵌套字段
如果 JSON 嵌套只有一层(比如某列值是 {"name": "Alice", "age": 30}),pandas.json_normalize 是最直接的选择。它能把字典结构自动拆成多列,比手写 apply(pd.Series) 更稳定、支持路径定位。
- 常见错误:直接对含字典的 Series 调用
.str方法(如df["info"].str["name"]),会报AttributeError: Can only use .str accessor with string values - 正确做法:先确认该列类型是
dict或str,若是字符串需先用json.loads转换,再传给json_normalize - 关键参数:
record_path用于指定嵌套数组路径(如"orders.items"),meta用于保留外层字段(如用户 ID) - 性能注意:对大 DataFrame 多次调用
json_normalize比批量处理慢,建议先用pd.concat合并后再展开
用 apply + pd.Series 处理不规则或混合类型嵌套
当某列中部分值是字典、部分是 None、部分是空字符串或非法 JSON 字符串时,json_normalize 会直接报错或丢行。这时得自己加容错逻辑。
- 典型错误现象:
ValueError: dictionaries must have the same keys—— 因为不同行的字典 key 不一致 - 推荐写法:
df["detail"].apply(lambda x: pd.Series(x) if isinstance(x, dict) else pd.Series()),避免json.loads在非字符串上崩溃 - 别用
eval()解析 JSON 字符串,存在安全风险;优先用json.loads()并包一层try/except - 如果嵌套深度超过两层(如
{"a": {"b": {"c": 1}}}),apply比json_normalize更容易控制展开粒度
用 ast.literal_eval 替代 json.loads 处理 Python 字面量格式
有些数据导出时把字典存成了字符串形式但不是标准 JSON(例如用单引号、True 小写、含注释),json.loads 会失败,而 ast.literal_eval 能安全解析合法 Python 字面量。
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
- 错误示例:
json.loads("{'name': 'Bob'}")→JSONDecodeError;但ast.literal_eval("{'name': 'Bob'}")成功 - 必须配合
isinstance(x, str)判断,否则对已经是 dict 的值调用literal_eval会报错 - 不支持 JSON 中常见的
null、Infinity等,仅限dict/list/str/int/float/bool/None - 速度略慢于
json.loads,但胜在兼容性——尤其面对爬虫或旧系统导出的“伪 JSON”字段时很实用
避免 pd.DataFrame(...).explode() 误炸多级嵌套
explode 只适合扁平化 list 类型列,若对已展开的 dict 列再 explode,会把每个 key 当作一个元素炸开,结果完全不可控。
立即学习“Python免费学习笔记(深入)”;
- 典型翻车场景:先用
json_normalize得到items列(内容是[{"id":1},{"id":2}]),然后直接.explode("items")—— 这步是对的;但如果接着对items列再.explode(),就会把{"id":1}拆成两个元素"id"和1 - 正确链式操作顺序:先
json_normalize或apply把嵌套 dict 拆成子 DataFrame,再对其中的 list 列explode,最后用json_normalize处理爆炸后的 dict 元素 - 检查爆炸后 shape 是否异常膨胀(比如行数突然变成原来的 100 倍),往往是没提前过滤空 list 或
None导致

















