Сообщение REST с использованием Python-Request

Почему этот простой код не отправляет данные POST в мою службу:

import requests
import json

data = {"data" : "24.3"}
data_json = json.dumps(data)
response = requests.post(url, data=data_json)
print response.text

И мой сервис разработан с использованием WCF следующим образом:

  [OperationContract]
  [WebInvoke(Method = "POST", UriTemplate = "/test", ResponseFormat =    
      WebMessageFormat.Json,RequestFormat=WebMessageFormat.Json)]
  string test(string data );

Примечание. Если удалить входной параметр data, все работает нормально, в чем может быть проблема.


person Suave Nti    schedule 18.12.2012    source источник
comment
Когда вы говорите, что это не работает, что именно вы имеете в виду? Судя по последнему примечанию, он больше, чем просто игнорирует мои данные (потому что без данных все работает нормально), но что именно тогда делает?   -  person abarnert    schedule 19.12.2012
comment
Что ж, я думаю, что нашел проблему. Это с {data: 24.3} .. по некоторым причинам мне нужно заключить это как строку, когда мой запрос проходит .. вот так {data: 24.3} .. кто-нибудь хочет объяснить причины?   -  person Suave Nti    schedule 19.12.2012
comment
Вы пробовали data = {"data": 24.3} (примечание: число с плавающей запятой, а не строку)? Я не знаю WCF, но вот другая интерпретация: string test(string data) может означать, что ваш сервер ожидает в качестве входных данных единственную строку (data_json = '"something"' (примечание: это строка Python, содержащая текст json, представляющий строку json)), и это не так. не ожидаю объект json. Строго говоря, application / json должно представлять либо объект json (например, data_json = '{"a", 1}'), либо массив json (например, data_json = '[1,2,3]'), поэтому неправильно принимать только строку.   -  person jfs    schedule 19.12.2012


Ответы (1)


Вам необходимо установить заголовок типа контента:

data = {"data" : "24.3"}
data_json = json.dumps(data)
headers = {'Content-type': 'application/json'}

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

Если я установлю url на http://httpbin.org/post, этот сервер вернет мне то, что было опубликовано:

>>> import json
>>> import requests
>>> import pprint
>>> url = 'http://httpbin.org/post'
>>> data = {"data" : "24.3"}
>>> data_json = json.dumps(data)
>>> headers = {'Content-type': 'application/json'}
>>> response = requests.post(url, data=data_json, headers=headers)
>>> pprint.pprint(response.json())
{u'args': {},
 u'data': u'{"data": "24.3"}',
 u'files': {},
 u'form': {},
 u'headers': {u'Accept': u'*/*',
              u'Accept-Encoding': u'gzip, deflate, compress',
              u'Connection': u'keep-alive',
              u'Content-Length': u'16',
              u'Content-Type': u'application/json',
              u'Host': u'httpbin.org',
              u'User-Agent': u'python-requests/1.0.3 CPython/2.6.8 Darwin/11.4.2'},
 u'json': {u'data': u'24.3'},
 u'origin': u'109.247.40.35',
 u'url': u'http://httpbin.org/post'}
>>> pprint.pprint(response.json()['json'])
{u'data': u'24.3'}

Если вы используете requests версию 2.4.2 или новее, вы можете оставить кодировку JSON библиотеке; он также автоматически установит для вас правильный заголовок Content-Type. Передайте данные для отправки в формате JSON в аргумент ключевого слова json:

data = {"data" : "24.3"}
response = requests.post(url, json=data)
person Martijn Pieters    schedule 18.12.2012
comment
Пробовал с Content-type ранее, но безуспешно. Есть ли проблемы с моим WCF .. Если я удалю параметр ввода, я могу вызвать URL-адрес. Я не знаю, в чем может быть проблема. - person Suave Nti; 19.12.2012
comment
Что ж, я думаю, что нашел проблему. Это с {"data" : "24.3"} .. по некоторым причинам мне нужно заключить это как строку, когда мой запрос проходит ... вот так {data: 24.3} .. кто-нибудь хочет объяснить причины? - person Suave Nti; 19.12.2012
comment
@GJSJ: тогда вы больше не отправляете объект JSON, а строку JSON. Это будет проблема на стороне сервера, не имеющая отношения к Python или requests. - person Martijn Pieters; 19.12.2012
comment
@GJSJ: просто попробуйте это с http://httpbin.org/post в качестве URL-адреса; он отвечает структурой JSON, включая json ключ, чтобы показать вам, какой JSON он получил, если вы отправляете JSON. - person Martijn Pieters; 19.12.2012
comment
согласованный с вашим сервером комментариев, ожидает строку json, поэтому мне нужно передать строку json, а не объект. Спасибо, ура !! - person Suave Nti; 19.12.2012
comment
@GJSJ: часто это означает, что тот, кто закодировал сервер, поместил эквивалент _1 _ / _ 2_ / в сценарий, даже если серверный контейнер или фреймворк уже выполнили декодирование, поэтому служба работает только в том случае, если клиент выполняет двойное кодирование данных. (Что, как указывает Дж. Ф. Себастьян, на самом деле незаконно для application/json, но большинству серверов все равно.) Правильное исправление - исправить сервер ... но если это не то, что вы контролируете, ваш обходной путь в основном эквивалентен двойное кодирование, поэтому работает так же хорошо. - person abarnert; 19.12.2012