web-dev-qa-db-ja.com

HTTP POSTリクエストボディはPythonでJSONエンコードする必要があるのはなぜですか?

外部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/101204

「GET/POSTを再度パラメーターをエンコードする必要がないかどうかに関係なく、引数として辞書を使用するだけでよいのです。」

シリアル化は必要ないように思えますか?

私のリクエストオブジェクト:

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

APIには、フォームエンコードされたデータではなくJSONエンコードされたデータが必要なようです。 dictdataパラメーターとして渡すと、データはフォームエンコードされます。文字列を渡すとき(json.dumps)、データはフォームエンコードされていません。

要求ドキュメントからの次の引用を検討してください。

通常、HTML形式のように、フォームでエンコードされたデータを送信します。これを行うには、辞書をデータ引数に渡すだけです。データの辞書は、リクエストが行われると自動的にフォームエンコードされます。

フォームエンコードされていないデータを送信することが何度もあります。辞書ではなく文字列を渡すと、そのデータは直接投稿されます。

たとえば、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))

参照:

34
Robᵩ

それらは構文的にはイテメンタルに見えますが、違いがあります。JSONはシリアル化されたオブジェクトの文字列表現です。この場合Python dict。この例では、シリアル化されたデータを文字列の形式で送信する必要があるため、シリアル化を実行するにはjson.dumpsが必要です。

編集

質問へのコメントで示唆されているように、それは使用されたAPIに関連していますが、それでもシリアル化は、オブジェクトをネットワーク経由で送信する途中のどこかで行わなければなりません。

1
Piotr Hajduga