简体   繁体   English

为什么HTTP POST请求体需要在Python中加入JSON?

[英]Why does HTTP POST request body need to be JSON enconded in Python?

I ran into this issue when playing around with an external API. 在玩外部API时遇到了这个问题。 I was sending my body data as a dictionary straight into the request and was getting 400 errors: 我将我的身体数据作为字典直接发送到请求中,并且收到了400个错误:

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

When I added a json.dumps wrap, it works: 当我添加一个json.dumps包装时,它可以工作:

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

I don't entirely understand why this is necessary, as dictionaries and JSON objects are syntactically identical. 我不完全理解为什么这是必要的,因为字典和JSON对象在语法上是相同的。 Can someone help me understand what is going on behind the scenes here? 有人可以帮我理解幕后发生的事情吗?

For completeness, here are my headers: 为了完整性,这是我的标题:

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

EDIT: 编辑:

I didn't mention this earlier but now I feel that it may be relevant. 我之前没有提到这个,但现在我觉得它可能是相关的。 I am using the Python Requests library, and another post seems to suggest that you should never have to encode parameters to a request object: https://stackoverflow.com/a/14804320/1012040 我正在使用Python Requests库,另一篇文章似乎建议你永远不必将参数编码到请求对象: https//stackoverflow.com/a/14804320/1012040

"Regardless of whether GET/POST you never have to encode parameters again, it simply takes a dictionary as an argument and is good to go." “无论GET / POST是否你再也不需要编码参数,它只需要一个字典作为参数,并且很好。”

Seems like serialization shouldn't be necessary? 好像序列化似乎不是必要的?

My request object: 我的请求对象:

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

Apparently your API requires JSON-encoded and not form-encoded data. 显然,您的API需要JSON编码而不是表单编码数据。 When you pass a dict in as the data parameter, the data is form-encoded. 当您将dict作为data参数传递时,数据将进行表单编码。 When you pass a string (like the result of json.dumps ), the data is not form-encoded. 传递字符串(如json.dumps的结果)时,数据不是表单编码的。

Consider this quote from the requests documentation: 请考虑请求文档中的引用:

Typically, you want to send some form-encoded data — much like an HTML form. 通常,您希望发送一些表单编码数据 - 非常类似于HTML表单。 To do this, simply pass a dictionary to the data argument. 为此,只需将字典传递给data参数即可。 Your dictionary of data will automatically be form-encoded when the request is made. 在请求发出时,您的数据字典将自动进行表单编码。

There are many times that you want to send data that is not form-encoded. 您有很多次要发送未经表单编码的数据。 If you pass in a string instead of a dict, that data will be posted directly. 如果传入字符串而不是dict,则会直接发布该数据。

For example, the GitHub API v3 accepts JSON-Encoded POST/PATCH 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))

Refs: 参考文献:

Although they seem syntatically itentical there is a difference: JSON is a string representation of serialized object; 虽然它们似乎是语法上的迭代,但是有一点不同:JSON是序列化对象的字符串表示; in this case Python dict. 在这种情况下Python字典。 In this example you need to send serialized data in a form of string and thus json.dumps is necessary to perform the serialization. 在此示例中,您需要以字符串形式发送序列化数据,因此需要json.dumps来执行序列化。

edit 编辑

As suggested in comments to the question it is relative to used API, but nevertheless the serialization must be done somewhere along the way to send an object over the wire. 正如对问题的评论所建议的那样,它与使用过的API有关,但是序列化必须在整个过程中通过线路发送对象的某个地方完成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM