Comment envoyer une requête POST en JSON?


105
data = {
        'ids': [12, 3, 4, 5, 6 , ...]
    }
    urllib2.urlopen("http://abc.com/api/posts/create",urllib.urlencode(data))

Je souhaite envoyer une demande POST, mais l'un des champs doit être une liste de nombres. Comment puis je faire ça ? (JSON?)


1
N'est-ce pas déjà une liste de chiffres?
Waynn Lue

Cela ne peut pas être répondu sans savoir quel type d'entrée attend l'API.
Niklas B.

1
@WaynnLue, le serveur d'API obtient cela sous forme de chaîne, pas de liste.
TIMEX

1
Dois-je définir les en-têtes comme "application / json" ou quelque chose comme ça?
TIMEX

Réponses:


154

Si votre serveur s'attend à ce que la requête POST soit json, vous devrez alors ajouter un en-tête et sérialiser les données de votre requête ...

Python 2.x

import json
import urllib2

data = {
        'ids': [12, 3, 4, 5, 6]
}

req = urllib2.Request('http://example.com/api/posts/create')
req.add_header('Content-Type', 'application/json')

response = urllib2.urlopen(req, json.dumps(data))

Python 3.x

https://stackoverflow.com/a/26876308/496445


Si vous ne spécifiez pas l'en-tête, ce sera le application/x-www-form-urlencodedtype par défaut .


J'ai une question. est-il possible d'ajouter plusieurs éléments dans l'en-tête ... comme le type de contenu et l'ID client ... @jdi
Omar Jandali

@OmarJandali, il suffit d'appeler à add_header()nouveau, pour chaque en-tête que vous souhaitez ajouter.
jdi

J'ai le code suivant mais il n'imprime rien. il était censé imprimer l'url et les en-têtes mais rien n'a été imprimé ... req = urllib.Request('http://uat-api.synapsefi.com') req.add_header('X-SP-GATEWAY', 'client_id_asdfeavea561va9685e1gre5ara|client_secret_4651av5sa1edgvawegv1a6we1v5a6s51gv') req.add_header('X-SP-USER-IP', '127.0.0.1') req.add_header('X-SP-USER', '| ge85a41v8e16v1a618gea164g65') req.add_header('Content-Type', 'application/json') print(req)...
Omar Jandali

urllib2 n'a pas été reconnu donc j'ai juste utilisé urllib. J'obtiens également une erreur avec la demande. The view tab.views.profileSetup didn't return an HttpResponse object. It returned None instead. @jdi
Omar Jandali

@OmarJandali, gardez à l'esprit que cette réponse a été donnée à l'origine en 2012, sous python 2.x. Vous utilisez Python3 donc les importations seront différentes. Ce serait maintenant import urllib.requestet urllib.request.Request(). De plus, l'impression de l'objet req n'a rien d'intéressant. Vous pouvez clairement voir que les en-têtes ont été ajoutés en imprimant req.headers. Au-delà de cela, je ne sais pas pourquoi cela ne fonctionne pas dans votre application.
jdi


66

pour python 3.4.2 j'ai trouvé que ce qui suit fonctionnera:

import urllib.request
import json      

body = {'ids': [12, 14, 50]}  
myurl = "http://www.testmycode.com"

req = urllib.request.Request(myurl)
req.add_header('Content-Type', 'application/json; charset=utf-8')
jsondata = json.dumps(body)
jsondataasbytes = jsondata.encode('utf-8')   # needs to be bytes
req.add_header('Content-Length', len(jsondataasbytes))
response = urllib.request.urlopen(req, jsondataasbytes)

1
Python3.6.2 cela a fonctionné. Seul l'ajout d'en-tête avec req.add_header (...) a fonctionné pour moi.
Shalin LK

18

Cela fonctionne parfaitement pour Python 3.5 , si l'URL contient une valeur de chaîne de requête / paramètre,

URL de la requête = https://bah2.com/ws/rest/v1/concept/
Valeur du paramètre = 21f6bb43-98a1-419d-8f0c-8133669e40ca

import requests

url = 'https://bahbah2.com/ws/rest/v1/concept/21f6bb43-98a1-419d-8f0c-8133669e40ca'
data = {"name": "Value"}
r = requests.post(url, auth=('username', 'password'), verify=False, json=data)
print(r.status_code)

7
dans votre snipper de code, la variable d'en-têtes reste inutilisée
shookees

4

Vous devez ajouter un en-tête, ou vous obtiendrez une erreur http 400. Le code fonctionne bien sur python2.6, centos5.4

code:

    import urllib2,json

    url = 'http://www.google.com/someservice'
    postdata = {'key':'value'}

    req = urllib2.Request(url)
    req.add_header('Content-Type','application/json')
    data = json.dumps(postdata)

    response = urllib2.urlopen(req,data)

2

Voici un exemple d'utilisation de l'objet urllib.request de la bibliothèque standard Python.

import urllib.request
import json
from pprint import pprint

url = "https://app.close.com/hackwithus/3d63efa04a08a9e0/"

values = {
    "first_name": "Vlad",
    "last_name": "Bezden",
    "urls": [
        "https://twitter.com/VladBezden",
        "https://github.com/vlad-bezden",
    ],
}


headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
}

data = json.dumps(values).encode("utf-8")
pprint(data)

try:
    req = urllib.request.Request(url, data, headers)
    with urllib.request.urlopen(req) as f:
        res = f.read()
    pprint(res.decode())
except Exception as e:
    pprint(e)

1

Dans le dernier package de requêtes, vous pouvez utiliser le jsonparamètre dans la requests.post()méthode pour envoyer un dict json, et l' Content-Typeen-tête in sera défini sur application/json. Il n'est pas nécessaire de spécifier explicitement l'en-tête.

import requests

payload = {'key': 'value'}

requests.post(url, json=payload)

Notez que cela entraînera un JSON POSTÉ avec des guillemets simples, ce qui est techniquement invalide.
Jethro

@Jethro Avez-vous observé des erreurs lors de l'utilisation de guillemets simples? Il est valide d'utiliser des guillemets simples en Python. Personnellement, je n'ai rencontré aucun problème à ce sujet.
jdhao

Aah excuses Je me suis trompé, je pensais que mon serveur recevait du JSON à guillemets simples mais cela s'est avéré être un problème séparé et un débogage trompeur. Merci, c'est beaucoup plus ordonné que d'avoir à spécifier l'en-tête manuellement!
Jethro

0

Celui-ci fonctionne bien pour moi avec apis

import requests

data={'Id':id ,'name': name}
r = requests.post( url = 'https://apiurllink', data = data)
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.