Jak wysłać żądanie POST jako JSON?


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

Chcę wysłać żądanie POST, ale jedno z pól powinno być listą liczb. Jak mogę to zrobić ? (JSON?)


1
Czy to nie jest już lista liczb?
Waynn Lue

Nie można odpowiedzieć na to pytanie, nie wiedząc, jakiego rodzaju danych wejściowych oczekuje interfejs API.
Niklas B.

1
@WaynnLue serwer API pobiera to jako ciąg znaków, a nie listę.
TIMEX

1
Czy muszę ustawić nagłówki jako „application / json” czy coś takiego?
TIMEX

Odpowiedzi:


154

Jeśli twój serwer oczekuje, że żądanie POST będzie json, musisz dodać nagłówek, a także serializować dane dla żądania ...

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


Jeśli nie określisz nagłówka, będzie to application/x-www-form-urlencodedtyp domyślny .


Mam pytanie. czy możliwe jest dodanie wielu elementów w nagłówku ... takich jak typ treści i identyfikator klienta ... @jdi
Omar Jandali

@OmarJandali, po prostu zadzwoń add_header()ponownie, dla każdego nagłówka, który chcesz dodać.
jdi,

Mam następujący kod, ale nic nie drukuje. miał wydrukować adres URL i nagłówki, ale nic nie zostało wydrukowane ... 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 nie zostało rozpoznane, więc właśnie użyłem urllib. Otrzymuję również błąd dotyczący żądania. The view tab.views.profileSetup didn't return an HttpResponse object. It returned None instead. @jdi
Omar Jandali

@OmarJandali, pamiętaj, że ta odpowiedź została pierwotnie udzielona w 2012 roku pod pythonem 2.x. Używasz Python3, więc import będzie inny. Teraz będzie import urllib.requesti urllib.request.Request(). Ponadto wydrukowanie obiektu req nie robi nic interesującego. Możesz wyraźnie zobaczyć, że nagłówki zostały dodane przez drukowanie req.headers. Poza tym nie jestem pewien, dlaczego nie działa w Twojej aplikacji.
jdi,


66

dla pythona 3.4.2 stwierdziłem, że będzie działać:

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 to zadziałało. U mnie zadziałało tylko dodanie nagłówka z req.add_header (...).
Shalin LK

18

Działa to idealnie w przypadku Python 3.5, gdy adres URL zawiera ciąg zapytania / wartość parametru,

URL żądania = https://bah2.com/ws/rest/v1/concept/
Wartość parametru = 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
we fragmencie kodu zmienna nagłówków pozostaje nieużywana
shookees

4

Musisz dodać nagłówek lub otrzymasz błąd http 400. Kod działa dobrze na python2.6, centos5.4

kod:

    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

Oto przykład użycia obiektu urllib.request ze standardowej biblioteki Pythona.

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

W najnowszym pakiecie żądań możesz użyć jsonparametru w requests.post()metodzie, aby wysłać dict json, a Content-Typenagłówek in zostanie ustawiony na application/json. Nie ma potrzeby jawnego określania nagłówka.

import requests

payload = {'key': 'value'}

requests.post(url, json=payload)

Zauważ, że spowoduje to POSTed json z pojedynczymi cudzysłowami, co jest technicznie nieprawidłowe.
Jethro

@Jethro Czy zauważyłeś błędy podczas używania apostrofów? W Pythonie można używać pojedynczych cudzysłowów. Osobiście nie napotkałem żadnych problemów z tym związanych.
jdhao

Ach przepraszam, pomyliłem się, myślałem, że mój serwer otrzymuje pojedyncze cudzysłowy JSON, ale okazało się, że to osobny problem i pewne wprowadzające w błąd debugowanie. Pozdrawiam, to znacznie prostsze rozwiązanie niż ręczne określanie nagłówka!
Jethro

0

Ten działa dobrze dla mnie z apis

import requests

data={'Id':id ,'name': name}
r = requests.post( url = 'https://apiurllink', data = data)
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.