理解 HTTP POST 请求中的 json 和 data 参数

在使用 Python 发送 HTTP POST 请求时(无论是使用 requests 还是 aiohttp),json 和 data 参数有明确的区别和使用场景。理解这些区别对正确构建请求至关重要。

关键区别

特性 json 参数 data 参数
内容类型 自动设置为 application/json 需要手动设置(默认是 application/x-www-form-urlencoded)
数据处理 自动序列化 Python 对象为 JSON 需要手动序列化
使用场景 API 请求(JSON-RPC, RESTful API) 表单提交、文件上传、自定义格式
编码 UTF-8 取决于内容类型
易用性 更简单(自动处理) 需要更多手动工作
  1. 何时使用 data

参数: 使用场景:

  1. 表单提交(HTML 表单数据):

    python

    复制代码
    form_data = {"username": "john", "password": "secret"}
    response = requests.post("https://example.com/login", data=form_data)
  2. 文件上传:

    python

    复制代码
    files = {"file": open("report.pdf", "rb")}
    response = requests.post("https://example.com/upload", files=files)
  3. 发送原始文本(非 JSON):

    python

    复制代码
    xml_data = "<user><name>John</name></user>"
    response = requests.post("https://example.com/api", 
                            data=xml_data,
                            headers={"Content-Type": "application/xml"})
  4. 多部分表单数据:

    python

    复制代码
    from aiohttp import FormData
    
    form = FormData()
    form.add_field("username", "john")
    form.add_field("avatar", open("avatar.jpg", "rb"), 
                  filename="avatar.jpg",
                  content_type="image/jpeg")
    
    async with session.post(url, data=form) as response:
  5. 自定义内容类型:

    python

    复制代码
    custom_data = "custom format data"
    response = requests.post("https://example.com/api", 
                            data=custom_data,
                            headers={"Content-Type": "text/plain"})

2. 何时使用 json 参数

使用场景:

  • 当 API 期望接收 JSON 格式的数据时(大多数现代 API 使用 JSON)

  • 当需要发送结构化数据(字典、列表等)

  • 当 API 文档指定请求体应为 JSON

示例:

python

复制代码
import requests

data = {"name": "John", "age": 30}
response = requests.post("https://api.example.com/users", json=data)

在 aiohttp 中:

python

复制代码
async with session.post(url, json=params) as response:

优点:

  1. 自动设置 Content-Type: application/json 头

  2. 自动将 Python 对象序列化为 JSON

  3. 简化代码

3. 最佳实践建议

  1. 推荐使用 json=params:

    python

    复制代码
    response = requests.post(url, headers=headers, json=params, timeout=60)
    • 更简洁

    • 更安全(自动处理序列化)

    • 自动设置正确的 Content-Type

  2. 如果使用 data,必须手动序列化:

    python

    复制代码
    response = requests.post(url, headers=headers, data=json.dumps(params), timeout=60)
    • 确保传递的是字符串,不是字典, 手动将`params`字典序列化为JSON字符串,然后通过`data`参数发送

    • 确保设置了正确的 Content-Type

  3. 避免使用 data=params:

    • 这总是错误的,除非您确实想发送表单数据, 这会将`params`字典编码为`application/x-www-form-urlencoded`格式(即表单数据),而不是JSON。

    • 对于 JSON API,会导致服务器解析错误

相关推荐
沫璃染墨11 小时前
从零入门计算机网络系列(十四):TCP报文与字节流本质——从数据封装到报文边界
linux·服务器·网络·网络协议·tcp/ip·tcp
byte轻骑兵13 小时前
【LMP】规范精讲[13]: 参数的户口本、公钥的集装箱与出厂的兜底值
人工智能·网络协议·人机交互·lmp·蓝牙链路管理
流浪00114 小时前
计算机网络篇17:传输层——TCP 超时重传、三次握手与四次挥手,TIME_WAIT 为什么要等 2MSL
网络协议·tcp/ip·计算机网络·三次握手·四次挥手·超时重传
视觉小萌新1 天前
AI Class 3 · Chapter 2-3:函数、异常、文件读写+JSON / JSONL 读写(小白版)
人工智能·python·json
AI 编程助手GPT1 天前
curl 返回成功就能收文件?用本地 HTTP 验证错误页与超时
网络·网络协议·http
流浪0011 天前
计算机网络篇16:传输层——TCP 报头属性字段:16 位窗口大小撑起流量控制,六个标志位标识报文类型
网络协议·tcp/ip·计算机网络·urg紧急指针·tcp报头
apollo_qwe1 天前
接口超时了,前端为什么不能直接重试?
javascript·http
Jongkhurun1 天前
以太网的最小帧长为什么是 64 字节:从 CSMA/CD 冲突窗口推导 64 Byte
网络协议
honsor2 天前
SNMP 读取以太网温湿度传感器数据,监控平台对接实操
物联网·网络协议·tcp/ip
翊众建站2 天前
用 JSON-LD 给企业官网做结构化数据:LocalBusiness 与 FAQPage 实践笔记
人工智能·搜索引擎·json