使用pandas json_normalize触发Must be list or null TypeError的解决问询
问题解决:pandas json_normalize 处理嵌套JSON时的TypeError及缺失值填充
问题根源
触发TypeError的核心原因是:json_normalize的record_path参数要求对应路径的值必须是列表或null,但你的数据里loc对应的是字典类型,不符合要求。另外注意你示例中的JSON存在重复键g,Python字典会自动保留最后一个键值对,导致前面的g: {'value': '2.0', 'text': 'xxx'}被后面的g:[]覆盖,这会影响最终结果,需要先修正这个问题。
解决方案
1. 直接调整数据结构(若允许修改原始数据)
把loc对应的字典包装成列表,满足record_path的要求,同时处理重复键问题:
import pandas as pd import numpy as np df = pd.DataFrame({ 'id': [0, 1], 'j': [ {'type': 's', 'loc': [{'s': {'value': '0.0', 'text': 'xxx'}, 'ps': {'value': '0.0', 'text': 'xxx'}, 'g': {'value': '2.0', 'text': 'xxx'}}]}, {'type': 's', 'loc': [{'s': {'value': '0.0', 'text': 'xxx'}, 'ps': {'value': '0.0', 'text': 'xxx'}, 'g': {'value': '2.0', 'text': 'xxx'}}]} ] }) # 使用json_normalize,errors='ignore'忽略不存在的键 dff = pd.json_normalize(df['j'], record_path=['loc'], meta=['id'], errors='ignore') # 空字符串或缺失值填充为np.nan dff = dff.replace('', np.nan).fillna(np.nan) print(dff)
2. 不修改原始数据的处理方式
如果无法调整原始数据,先对loc字段单独做字典扁平化,再合并id列:
import pandas as pd import numpy as np df = pd.DataFrame({ 'id': [0, 1], 'j': [ {'type': 's', 'loc': {'s': {'value': '0.0', 'text': 'xxx'}, 'ps': {'value': '0.0', 'text': 'xxx'}, 'g': {'value': '2.0', 'text': 'xxx'}}}, {'type': 's', 'loc': {'s': {'value': '0.0', 'text': 'xxx'}, 'ps': {'value': '0.0', 'text': 'xxx'}, 'g': {'value': '2.0', 'text': 'xxx'}}} ] }) # 扁平化每个loc字典 flattened_loc = df['j'].apply(lambda x: pd.json_normalize(x['loc'])).explode().reset_index(drop=True) # 合并id列 dff = pd.concat([flattened_loc, df['id'].reset_index(drop=True)], axis=1) # 填充缺失值 dff = dff.replace('', np.nan).fillna(np.nan) print(dff)
3. 处理重复键的特殊情况
如果原始数据确实存在重复键,先用工具函数修复,将重复键的值合并为列表:
import pandas as pd import numpy as np from collections import defaultdict def fix_duplicate_keys(obj): """修复JSON重复键,将同键值合并为列表""" if isinstance(obj, dict): new_obj = defaultdict(list) for k, v in obj.items(): new_obj[k].append(fix_duplicate_keys(v)) # 长度为1的列表转回原值 return {k: v[0] if len(v)==1 else v for k, v in new_obj.items()} elif isinstance(obj, list): return [fix_duplicate_keys(item) for item in obj] else: return obj # 修复数据中的重复键 df['j'] = df['j'].apply(fix_duplicate_keys) # 扁平化并合并 flattened_loc = df['j'].apply(lambda x: pd.json_normalize(x['loc'])).explode().reset_index(drop=True) dff = pd.concat([flattened_loc, df['id'].reset_index(drop=True)], axis=1) dff = dff.replace('', np.nan).fillna(np.nan) print(dff)
最终输出
运行上述代码后,将得到符合预期的结果:
s.value s.text ps.value ps.text g.value g.text id 0 0.0 xxx 0.0 xxx 2.0 xxx 0 1 0.0 xxx 0.0 xxx 2.0 xxx 1
内容的提问来源于stack exchange,提问作者kms
相关产品推荐
相关产品推荐

