这类问题我又碰上了一次。把上游的嵌套 JSON 用 json_normalize 展平后写入特征表,列名变成 user.profile.city 这种带点的形式,下游用方括号取 key 全部取不到,改走 SQL 又得给整列名加引号,整条链路都在打补丁。
第一反应是「下游按层级解析,不认扁平化后的键」,验证下来不成立。
真正麻烦的地方在于,几个原因的现象几乎一样。展平用点号做分隔符,和下游的路径语法冲突;列名里带大写和空格,数据库自动转成小写;同一份数据两次展平的层级深度不一致。
第一件事是列出展平后的列名看冲突在哪
python -c "import pandas as pd;print(list(pd.json_normalize({'user':{'profile':{'city':'杭州'}}}).columns))"
接着改用下划线分隔并统一小写
python -c "import pandas as pd;d=pd.json_normalize({'user':{'profile':{'city':'杭州'}}},sep='_');d.columns=[c.lower() for c in d.columns];print(list(d.columns))"
入库前校验列名是否符合命名规则
python check_columns.py --table feature_user --pattern '^[a-z][a-z0-9_]*$'
等前面都确认过,再用改名后的列跑一次端到端查询
curl -s 'http://api:8080/feature?uid=u1' | jq '.user_profile_city'
怎么算真的好了,看的是同一批现象。特征表列名全部是小写下划线形式,查询接口能直接取到城市字段,下游不再需要给列名加引号。
点号在 JSON 路径、SQL 标识符和列名里含义不同,展平分隔符要选一个三者都不冲突的字符。拖得越久,排查成本越高,因为现场状态会被后续操作覆盖。
