web-dev-qa-db-de.com

Warum funktioniert HTTP? POST Anforderungstext muss in Python JSON-codiert sein?

Ich bin auf dieses Problem gestoßen, als ich mit einer externen API herumspielte. Ich schickte meine Körperdaten als Wörterbuch direkt in die Anfrage und erhielt 400 Fehler:

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

Wenn ich einen json.dumps-Wrap hinzugefügt habe, funktioniert es:

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

Ich verstehe nicht ganz, warum dies notwendig ist, da Wörterbücher und JSON-Objekte syntaktisch identisch sind. Kann mir jemand helfen zu verstehen, was hier hinter den Kulissen los ist?

Der Vollständigkeit halber hier meine Header:

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

BEARBEITEN:

Ich habe das nicht früher erwähnt, aber jetzt habe ich das Gefühl, dass es relevant sein könnte. Ich verwende die Python-Anforderungsbibliothek, und ein anderer Beitrag scheint zu suggerieren, dass Sie niemals Parameter für ein Anforderungsobjekt kodieren müssen: https://stackoverflow.com/a/14804320/1012040

"Unabhängig davon, ob GET/POST Sie nie wieder Parameter codieren müssen, es ist einfach ein Wörterbuch als Argument und es ist gut zu gehen."

Scheint, Serialisierung sollte nicht notwendig sein?

Mein Anfrageobjekt:

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

Anscheinend erfordert Ihre API JSON-codierte und keine formularkodierten Daten. Wenn Sie eine dict in als data-Parameter übergeben, werden die Daten in einem Formular codiert. Wenn Sie eine Zeichenfolge übergeben (wie das Ergebnis von json.dumps), werden die Daten nicht formcodiert.

Beachten Sie dieses Zitat aus der Anforderungsdokumentation:

Normalerweise möchten Sie formularkodierte Daten senden - ähnlich wie ein HTML-Formular. Dazu übergeben Sie einfach ein Wörterbuch an das Datenargument. Ihr Datenwörterbuch wird bei der Anforderung automatisch in ein Formular umgewandelt.

Oft möchten Sie Daten senden, die nicht formcodiert sind. Wenn Sie einen String anstelle eines Diktats übergeben, werden diese Daten direkt gebucht.

Zum Beispiel akzeptiert die GitHub-API Version 3 JSON-kodierte POST/PATCH-Daten:

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

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

Refs: 

32
Robᵩ

Obwohl sie syntaktisch itentisch erscheinen, gibt es einen Unterschied: JSON ist eine Zeichenfolgendarstellung eines serialisierten Objekts. in diesem Fall Python-Dikt. In diesem Beispiel müssen Sie serialisierte Daten in Form einer Zeichenfolge senden. Daher ist json.dumps für die Serialisierung erforderlich.

bearbeiten

Wie in den Kommentaren zu der Frage vorgeschlagen, ist sie relativ zur verwendeten API. Trotzdem muss die Serialisierung irgendwo auf dem Weg erfolgen, um ein Objekt über das Kabel zu senden.

1
Piotr Hajduga