如何在aiohttp的POST请求中传递datetime类型数据?
解决aiohttp POST请求中datetime对象JSON序列化问题
问题原因
Python标准库的JSON编码器默认无法处理datetime对象,而aiohttp的session.post()方法中json参数使用的是默认序列化逻辑,因此会抛出TypeError: Object of type datetime is not JSON serializable错误。
解决方案
以下两种方案均不将datetime转换为字符串,而是用机器易解析的结构化数据或时间戳完成序列化:
方案1:自定义JSON编码器并配置到ClientSession
通过自定义JSONEncoder子类处理datetime对象,将其绑定到aiohttp的ClientSession中,让所有请求自动使用该编码器:
import asyncio import json from datetime import datetime from pprint import pprint import aiohttp # 自定义JSON编码器,将datetime转为时间戳(数字类型)或结构化字典 class DateTimeEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, datetime): # 可选:返回时间戳(数字) return obj.timestamp() # 可选:返回结构化字典,方便后端识别类型并还原 # return {"__type__": "datetime", "timestamp": obj.timestamp()} return super().default(obj) # 封装自定义序列化函数 def custom_json_serializer(obj): return json.dumps(obj, cls=DateTimeEncoder) payload = {'key1': 'value1', 'key2': 'value2', 'now': datetime.now()} async def main(): # 初始化ClientSession时指定自定义序列化逻辑 async with aiohttp.ClientSession(json_serialize=custom_json_serializer) as session: async with session.post('http://httpbin.org/post', json=payload) as resp: pprint(await resp.json()) asyncio.run(main())
方案2:手动序列化并通过data参数传递
手动用自定义逻辑序列化payload,通过data参数发送,同时设置正确的Content-Type请求头:
import asyncio import json from datetime import datetime from pprint import pprint import aiohttp payload = {'key1': 'value1', 'key2': 'value2', 'now': datetime.now()} async def main(): # 用lambda函数快速处理datetime,直接返回时间戳 serialized_payload = json.dumps( payload, default=lambda o: o.timestamp() if isinstance(o, datetime) else o ) async with aiohttp.ClientSession() as session: async with session.post( 'http://httpbin.org/post', data=serialized_payload, headers={'Content-Type': 'application/json'} ) as resp: pprint(await resp.json()) asyncio.run(main())
说明
两种方案都避免了将datetime转为字符串,后端可根据序列化后的格式(时间戳或结构化字典),轻松将数据还原为datetime对象。
内容的提问来源于stack exchange,提问作者Альберт Александров
相关产品推荐
相关产品推荐

