使用Python调用Poke API创建SQL表时遇TypeError报错求助
问题:使用Python存储Poke API数据到SQL表时JSON序列化报错
尝试用Python调用Poke API,将前100个宝可梦信息存入PostgreSQL的JSONB字段,代码如下:
import psycopg2, json, requests, hidden # Load secrets secrets = hidden.secrets() conn = psycopg2.connect(host=secrets['host'], port=secrets['port'], database=secrets['database'], ..., connect_timeout=3) cur = conn.cursor() defaulturl = 'https://pokeapi.co/api/v2/pokemon?limit=100&offset=0' sql = ''' CREATE TABLE IF NOT EXISTS pokeapi (id SERIAL, body JSONB); ''' cur.execute(sql) response = requests.get(defaulturl) js = response.json() results = js['results'] for x in range(len(results)): body = requests.get(results[x]['url']) js_body = json.dumps(body) sql = f"INSERT INTO pokeapi (body) VALUES ('{js_body}'::JSONB)"; cur.execute(sql, (defaulturl)) print('Closing database connection...') conn.commit() cur.close()
运行时报错:
TypeError: Object of type Response is not JSON serializable
错误出现在js_body = json.dumps(body)这一行。
错误原因
requests.get()方法返回的是Response对象,它包含响应状态码、头部、内容等元信息,并不是直接可序列化的JSON数据。json.dumps()只能处理Python原生数据类型(如字典、列表等),无法直接序列化Response对象,因此抛出该错误。
修复方案及修正代码
针对问题做以下核心修改:
- 获取可序列化的JSON数据:调用Response对象的
.text直接获取响应的JSON字符串,或用.json()转为字典后再序列化; - 规避SQL注入风险:废弃字符串格式化拼接SQL的方式,改用参数化查询传递数据;
- 修正执行参数格式:确保参数元组格式正确(单个元素需加逗号),且参数与SQL占位符对应。
修正后的代码:
import psycopg2, json, requests, hidden # Load secrets secrets = hidden.secrets() conn = psycopg2.connect(host=secrets['host'], port=secrets['port'], database=secrets['database'], user=secrets['user'], password=secrets['password'], connect_timeout=3) cur = conn.cursor() defaulturl = 'https://pokeapi.co/api/v2/pokemon?limit=100&offset=0' # 创建表 sql = ''' CREATE TABLE IF NOT EXISTS pokeapi (id SERIAL, body JSONB); ''' cur.execute(sql) # 获取宝可梦列表 response = requests.get(defaulturl) js = response.json() results = js['results'] for result in results: # 获取单个宝可梦的JSON响应文本 pokemon_response = requests.get(result['url']) pokemon_json_str = pokemon_response.text # 参数化插入,避免SQL注入 sql = "INSERT INTO pokeapi (body) VALUES (%s::JSONB)" cur.execute(sql, (pokemon_json_str,)) # 注意元组的逗号 print('Closing database connection...') conn.commit() cur.close() conn.close() # 补充关闭数据库连接
内容的提问来源于stack exchange,提问作者hulio_entredas
相关产品推荐
相关产品推荐

