不修改源JSON将metadata对象转Python列表写入Postgres的问题
问题原因分析
- 你之前编写的列表推导式
read_data["metadata"] = [{key:value} for key,value in read_data["metadata"].items()]是把原本完整的metadata字典拆成了多个仅包含单个键值对的字典组成的列表,最终得到的结构为[{"namespace": "5.2.0"}, {"message_id": "3c80151b-fcf3-4cc3-ada0-635be5b5c95f"}, ..., {"version":"1.0.0"}]。循环读取时每个字典只有1个键有值,其余字段调用get()返回的都是None,最后一次循环赋值会把之前的字段都覆盖成NULL,所以永远只有metadata的最后一个键有值。 - 最初的
AttributeError: 'str' object has no attribute 'get'报错是因为你直接遍历了原本的metadata字典(遍历字典默认返回键的字符串,不是键值对),和JSON结构无关。
修复方案
你不需要拆分metadata字典,直接给原本的metadata对象外层套一层列表即可,效果和你手动改JSON加[]完全一致,替换你原来错误的列表推导式即可:
# 删掉原来的read_data["metadata"] = [{key:value} for key,value in read_data["metadata"].items()],替换成下面这行 read_data["metadata"] = [read_data["metadata"]]
修改后原有逻辑不需要做其他调整,即可正常读取所有metadata字段写入表中。
可选优化建议
你当前的逻辑是先插入价格数据(metadata字段留空)再做全表更新,其实可以插入数据时直接拼接metadata字段,省去全表更新步骤,性能更好:
# 提前读取metadata字段值 metadata = read_data["metadata"] meta_list = [ metadata["namespace"], metadata["message_id"], metadata["transmit_time"], metadata["message_type"], metadata["domain"], metadata["version"] ] def get_PricingData(): list_1 = read_data["prices"] for dic in list_1: price = dic.get("price") effective_date = dic.get("effective_date") strikethrough = dic.get("strikethrough") expiration_date = dic.get("expiration_date") modified_date = dic.get("modified_date") base_price = dic.get("base_price") sku_id = dic.get("sku_id") item_number = dic.get("item_number") trade_base_price = dic.get("trade_base_price") competitive_price = dic.get("competitive_price") # 直接拼接metadata值,不需要后续UPDATE data_pricing.append([price, effective_date, strikethrough, expiration_date, modified_date, base_price, sku_id, item_number, trade_base_price, competitive_price] + meta_list)
调整后可以把post_gre()函数里的UPDATE相关逻辑完全删除,减少数据库操作次数。
内容的提问来源于stack exchange,提问作者Data Engineer
相关产品推荐
相关产品推荐

