33

我在使用外部 API 时遇到了这个问题。我将我的身体数据作为字典直接发送到请求中,并收到 400 个错误:

data = {
  "someParamRange": {
    "to": 1000, 
    "from": 100
  }, 
  "anotherParamRange": {
    "to": True, 
    "from": False
  }
}

当我添加一个 json.dumps 包装时,它可以工作:

data = json.dumps({
  "someParamRange": {
    "to": 1000, 
    "from": 100
  }, 
  "anotherParamRange": {
    "to": True, 
    "from": False
  }
})

我不完全理解为什么这是必要的,因为字典和 JSON 对象在语法上是相同的。有人可以帮助我了解这里的幕后情况吗?

为了完整起见,这是我的标题:

headers = {'API-KEY': 'blerg', 'Accept-Encoding': 'UTF-8', 'Content-Type': 'application/json', 'Accept': '*/*', 'username': 'user', 'password': 'pwd'}

编辑:

我之前没有提到这一点,但现在我觉得它可能是相关的。我正在使用 Python Requests 库,另一篇文章似乎建议您永远不必将参数编码为请求对象:https ://stackoverflow.com/a/14804320/1012040

“无论是 GET/POST,您都不必再次对参数进行编码,它只需要一个字典作为参数就可以了。”

似乎不需要序列化?

我的请求对象:

response = requests.post(url, data=data, headers=headers)
4

2 回答 2

58

显然,您的 API 需要 JSON 编码而不是表单编码的数据。当您将 adict作为data参数传入时,数据是表单编码的。当您传递一个字符串(如 的结果json.dumps)时,数据不是形式编码的。

考虑请求文档中的这句话:

通常,您希望发送一些表单编码的数据——很像 HTML 表单。为此,只需将字典传递给 data 参数。发出请求时,您的数据字典将自动进行表单编码。

很多时候,您希望发送未进行表单编码的数据。如果您传入一个字符串而不是一个字典,则该数据将直接发布。

例如,GitHub API v3 接受 JSON 编码的 POST/PATCH 数据:

>>> import json
>>> url = 'https://api.github.com/some/endpoint'
>>> payload = {'some': 'data'}

>>> r = requests.post(url, data=json.dumps(payload))

参考:

于 2013-03-29T03:06:18.560 回答
1

虽然它们在语法上看起来是有区别的:JSON 是序列化对象的字符串表示;在这种情况下 Python 字典。在此示例中,您需要以字符串形式发送序列化数据,因此需要 json.dumps 来执行序列化。

编辑

正如对该问题的评论中所建议的那样,它与使用的 API 相关,但是序列化必须在沿途某处进行,以通过线路发送对象。

于 2013-03-28T23:51:19.037 回答