Using python 'requests' to send JSON boolean - python

I've got a really simple question, but I can't figure it out how to do it. The problem I have is that I want to send the following payload using Python and Requests:
{ 'on': true }
Doing it like this:
payload = { 'on':true }
r = requests.put("http://192.168.2.196/api/newdeveloper/lights/1/state", data = payload)
Doesn't work, because I get the following error:
NameError: name 'true' is not defined
Sending the true as 'true' is not accepted by my server, so that's not an option. Anyone a suggestion? Thanks!

You need to json encode it to get it to a string.
import json
payload = json.dumps({"on":True})

should be {'on': True}, capital T

Starting from requests 2.4.2, instead of passing in the payload with the data parameter, you can use the json parameter like this:
payload = {'on': True}
requests.put(url, json=payload)
And the request will be formatted correctly as a json payload (i.e. {'on': true}).

to make it be lower case like that (if that's what your endpoint requires) do in quotes {'on':'true'}

Related

Am I sending a this json data correctly using the python requests library?

I'm trying to send this json array to an API using request.post():
{
"insert": [
{
"data": "48bPRVkgvHwjG2VUTkPLaGazynZ6RxETuNGsYZNBrtb7ZkAUqY1NE2iGqoLd8EFsvhbDGW8gNb96Jce8fg2aiY8A5mbd8zf",
"tag": "0x1001"
}
]
}
I was told the json post has to be in an array by one of the devs at the site I'm posting to.
I also pored over these two examples in the API docs.1(edit emojiId section),2(adding an emoji id record)
What I tried so far is posting this dictionary:
{'insert': [{'data': '48bPRVkgvHwjG2VUTkPLaGazynZ6RxETuNGsYZNBrtb7ZkAUqY1NE2iGqoLd8EFsvhbDGW8gNb96Jce8fg2aiY8A5mbd8zf', 'tag': '0x1001'}]}
Using both of these post requests:
requests.post(base_url + '/emoji_id/🀘🐺🀘', json=dict_data, headers=headers)
requests.post(base_url + '/emoji_id/🀘🐺🀘', data=dict_data, headers=headers)
I then converted the dictionary to a string using
dict_data = json.dumps(dict_data, skipkeys=True, separators=(',', ':'))
and again sent it using both json and data.
Each returned a 405 error.
The next thing I tried is using the example this stack post to send a nested json. Here's my code for that attempt:
params = [{'data':'48bPRVkgvHwjG2VUTkPLaGazynZ6RxETuNGsYZNBrtb7ZkAUqY1NE2iGqoLd8EFsvhbDGW8gNb96Jce8fg2aiY8A5mbd8zf','tag':'0x1001'}]
# Tried above both with [ ] on outside making it a list and without
payload = {'insert': json.dumps(params, skipkeys=True, separators=(',', ':'))}
requests.post(base_url + '/emoji_id/🀘🐺🀘', json=payload, headers=headers)
Again, I used both json=payload and data=payload and again I tried it both as a dictionary and converting to a string using the same json.dumps method as above. Same as before each returned a 405 response.
My question is, am I using request.post() correctly in at least one of these attempts? If so, I must be missing something about what the API expects and can start down that rabbit hole.
#ewong nailed it. I didn't realize I had to use the patch method instead of the post method.
So my issue was fixed using:
requests.patch(base_url + '/emoji_id/🀘🐺🀘', json=dict_data, headers=headers)
instead of request.post. The difference between the two still seems subtle to me at this point but the example given in the API docs clearly show a patch method being used and that's what worked.

Mapbox API PUT Datasets Feature return "Provide a single Feature to insert"

I am trying to add a feature to the Dataset via Mapbox API using Python. I'm following this instruction https://docs.mapbox.com/api/maps/#update-a-dataset but keep getting this error:
{'message': 'Provide a single Feature to insert'}
The code looks like this:
rs = []
dictionary = {
"id":1,
"type":"Feature",
"properties":{},
"geometry":{"coordinates":[-83.750246, 42.269375],"type":"Point"}}
url = "https://api.mapbox.com/datasets/v1/voratima/"+dataset+"/features/1?access_token="+access_token
rs.append(grequests.put(url, data=dictionary, hooks = {'response' : do_something}))
grequests.map(rs, exception_handler=exception_handler)
I've tried the following but none of them work:
using requests instead of grequests
wrapping the dictionary with json.dumps()
changing the put parameter from data=dictionary to json=dictionary
Making sure the id for both data and URL are set to 1.
Postman of the exact same request does not have the error. What am I missing?
Given a dataset with dataset ID dataset exists, your request body looks ok.
Please add the header
headers = {'Content-type': 'application/json'}
Also can you check if you meet these specs:
This should be one individual GeoJSON feature, not a GeoJSON
FeatureCollection. If the GeoJSON feature has a top-level id property,
it must match the feature_id you use in the URL endpoint.
It turns out I forgot the header. Thanks to Mortiz for pointing that out. After the update I got
<Response [400]> {'message': 'Unexpected token i'}
That's because I need to wrap the dictionary inside json.dumps(). Then the error became
<Response [422]> {'message': 'Request URI does not match feature id'}
That's because the id in the dictionary has to be a string i.e. "id":"1" not "id":1. Here's the code that works:
rs = []
dictionary = {
"id":"1",
"type":"Feature",
"properties":{},
"geometry":{"coordinates":[-83.750246, 42.269375],"type":"Point"}}
headers = {'Content-type': 'application/json'}
url = "https://api.mapbox.com/datasets/v1/voratima/"+dataset+"/features/1?access_token="+access_token
rs.append(grequests.put(url, data=json.dumps(dictionary), headers=headers, hooks = {'response' : do_something}))
grequests.map(rs, exception_handler=exception_handler)

Python request.post Missing Required Param

I've been looking around and trying to get a post request to work, but I haven't found any luck. I keep getting a MISSING_REQUIRED_PARAM each time the request is being made. My following code is shown below.
def create_sign_group(group_name, header, url):
temp_header = header
temp_header['Content-Type'] = 'application/json'
temp_header['Accept'] = 'application/json'
data = {
"GroupCreationInfo": {
"groupName": group_name
}
}
res = requests.post(url + 'groups', headers=temp_header, data=json.dumps(data))
if res.status_code == 200:
print('{} Group Created...'.format(group_name))
else:
print(res.status_code)
print(res.headers)
print(res.text)
exit(res.status_code)
I've tried using json instead of data, but still getting the same error. Using a the REST API client I was able to successfully make the call. The rest client is shown below:
If anyone can point shine some knowledge and point me in the right direction I would greatly appreciate it. Take care.
You should assign headers=temp_header not headers=header. MISSING_REQUIRED_PARAM is often griping about the content type header, which, as you can see IS being included in your screenshot test.
So I figured it out, I guess I was passing the wrong payload into the data param. I changed the code to:
data = {
"groupName": group_name
}
It looks like I didn't need the "GroupCreationInfo" parameter.

How to return this valid json data in Python?

I tested using Python to translate a curl to get some data.
import requests
import json
username="abc"
password="123"
headers = {
'Content-Type': 'application/json',
}
params = (
('version', '2017-05-01'),
)
data = '{"text":["This is message one."], "id":"en-es"}'
response = requests.post('https://somegateway.service/api/abc', headers=headers, params=params, data=data, auth=(username, password))
print(response.text)
The above works fine. It returns json data.
It seems ["This is message one."] is a list. I want to use a variable that loads a file to replace this list.
I tried:
with open(f,"r",encoding='utf-8') as fp:
file_in_list=fp.read().splitlines()
toStr=str(file_in_list)
data = '{"text":'+toStr+', "id":"en-es"}'
response = requests.post('https://somegateway.service/api/abc', headers=headers, params=params, data=data, auth=(username, password))
print(response.text)
But it returned error below.
{
"code" : 400,
"error" : "Mapping error, invalid JSON"
}
Can you help? How can I have valid response.text?
Thanks.
update:
The content of f contains only five lines below:
This is message one.
this is 2.
this is three.
this is four.
this is five.
The reason your existing code fails is that str applied to a list of strings will only rarely give you valid JSON. They're not intended to do the same thing. JSON only allows double-quoted strings; Python allows both single- and double-quoted strings. And, unless your strings all happen to include ' characters, Python will render them with single quotes:
>>> print(["abc'def"]) # gives you valid JSON, but only by accident
["abc'def"]
>>> print(["abc"]) # does not give you valid JSON
['abc']
If you want to get the valid JSON encoding of a list of strings, don't try to trick str into giving you valid JSON by accident, just use the json module:
toStr = json.dumps(file_in_list)
But, even more simply, you shouldn't be trying to figure out how to construct JSON strings in the first place. Just create a dict and json.dumps the whole thing:
data = {"text": file_in_list, "id": "en-es"}
data_str = json.dumps(data)
Being able to do this is pretty much the whole point of JSON: it's a simple way to automatically serialize all of the types that are common to all the major scripting languages.
Or, even better, let requests do it for you by passing a json argument instead of a data argument:
data = {"text": file_in_list, "id": "en-es"}
response = requests.post('https://somegateway.service/api/abc', headers=headers, params=params, json=data, auth=(username, password))
This also automatically takes care of setting the Content-Type header to application/json for you. You weren't doing thatβ€”and, while many servers will accept your input without it, it's illegal, and some servers will not allow it.
For more details, see the section More complicated POST requests in the requests docs. But there really aren't many more details.
tldr;
toStr = json.dumps(file_in_list)
Explanation
Assuming your file contains something like
String_A
String_B
You need to ensure that toStr is:
Enclosed by [ and ]
Every String in the list is enclosed by quotation marks.
So your raw json (as a String) is equal to '{"text":["String_A", "String_B"], "id":"en-es"}'

requests.post with Python

I'm connecting to a login protected API with a Python script here below.
import requests
url = 'https://api.json'
header = {'Content-Type': 'application/x-www-form-urlencoded'}
login = ('kjji#snm.com', 'xxxxx')
mnem = 'inputRequests':'{'inputRequests':'[{'function':'GDSP','identifier':'ibm','mnemonic':'IQ_TOTAL_REV'}]}}
r = requests.post(url, auth=login, data=mnem, headers=header)
print(r.json())
The connection is established but I am getting an error from the API because of the format of the data request.The original format is here below. I cannot find a way to enter this in the mnem here above:
inputRequests={inputRequests:
[
{function:"xxx",identifier:"xxx",mnemonic:"xxx"},
]
}
The error given is
C:\Users\xxx\Desktop>pie.py
File "C:\Users\xxx\Desktop\pie.py", line 6
mnem={'inputRequests':'{'inputRequests':'[{'function':'xxx','identifier':'xx','mnemonic':'xxx'}]}}
^
SyntaxError: invalid syntax
I am unsure on how to proceed from here. I cannot find anything in the requests documentation that points to how to insert several variables in the data field.
The requests module in Python receive protogenic Python dict as the JSON data in post request but not a string. Therefore, you may try to define mnem like this:
mnem = {
'inputRequests':[
{'function':'GDSP',
'identifier':'ibm',
'mnemonic':'IQ_TOTAL_REV'
}
]}
the data parameter should be a dictionary.
therefore to pass the three parameters try using:
mnem = {'function':'GDSP','identifier':'ibm','mnemonic':'IQ_TOTAL_REV'}

Categories

Resources