Here's my function which connects to an API:
def order_summary():
"""Get order summary for a specific order"""
# Oauth2 params
headerKey = api_login()
headers = {'Authorization': headerKey}
# Payload params
payloadOrderSum = {
"domainId": 15,
"domainName": "SGL",
"orderId": 3018361
}
# API response
orderSumResp = requests.post(url + "order/summary", data=payloadOrderSum, headers=headers)
print(orderSumResp.content)
The API expects a JSON array as Payload Params which essentially looks like that:
[
{
"domainId": 0,
"domainName": "string",
"orderId": 0
}
]
The other endpoints I coded for on this API didn't need for the params to be an array so I could just use them as is and send them as a dictionary and it worked.
I've tried a couple things using the JSON library but I can't seem to get it to work. I saw that the JSonEncoder converts lists and tuples to JSON arrays but I couldn't figure it out.
Not sure what other info I could provide but just ask if there are any.
Thanks!
Wrap payloadOrderSum into a list:
payloadOrderSum = {
"domainId": 15,
"domainName": "SGL",
"orderId": 3018361
}
orderSumResp = requests.post(url + "order/summary", json=[payloadOrderSum], headers=headers)
Note that I used json kwarg instead of data (added in version 2.4.2).
dump your dict with json.dumps requests-doc
r = requests.post(url, data=json.dumps(payload))
It could help if you specify what you tried with the JSON library.
However, you might wanna try this if you haven't already done so:
import json
payloadOrderSum = json.dumps(
{
"domainId": 15,
"domainName": "SGL",
"orderId": 3018361
}
)
Related
How to transfer payload as a string in requests python?
my code:
def send():
url = "url"
cookies = {
"csrf_token":"",
"refresh_token":"",
"access_token":""
}
data = "id%5B%5D=52626995&id%5B%5D=52627067&result_element%5BNAME%5D=%D0%90%D1%80%D0%BA%D0%B0%D0%B4%D0%B8%D0%B9&result_element%5BMAIN_USER_ID%5D=8272126&result_element%5BTAGS%5D%5B%5D=559091&result_element%5BTAGS%5D%5B%5D=559091&result_element%5Bcfv%5D%5B664393%5D%5B%5D=%7B%22DESCRIPTION%22%3A%22WORK%22%2C%22VALUE%22%3A%2271111111111%22%7D&result_element%5Bcfv%5D%5B664393%5D%5B%5D=%7B%22DESCRIPTION%22%3A%22WORK%22%2C%22VALUE%22%3A%2271111111111%22%7D&result_element%5Bcfv%5D%5B1262415%5D=12&result_element%5Bcfv%5D%5B1256527%5D=3&result_element%5Bcfv%5D%5B1272573%5D=817683&result_element%5BLEADS%5D%5B%5D=36375665&result_element%5BID%5D=52627067"
resp = requests.post(url=url, cookies=cookies, data=data)
return resp
But i got error cause data must be dict
They are right. It has to be a dictionary. The data you have here is also an encoded dictionary. Using (https://www.url-encode-decode.com/) you can understand your data better.
id[]=52626995
id[]=52627067
result_element[NAME]=Аркадий
result_element[MAIN_USER_ID]=8272126
result_element[TAGS][]=559091
result_element[TAGS][]=559091
result_element[cfv][664393][]={"DESCRIPTION":"WORK","VALUE":"71111111111"}
result_element[cfv][664393][]={"DESCRIPTION":"WORK","VALUE":"71111111111"}
result_element[cfv][1262415]=12
result_element[cfv][1256527]=3
result_element[cfv][1272573]=817683
result_element[LEADS][]=36375665
result_element[ID]=52627067
As a normal python dictionary, this is the following
{
"id": [52626995, 52627067],
"result_element": {
"NAME": "Аркадий",
"MAIN_USER_ID": 8272126,
"TAGS": [559091, 559091],
"cfv": {
664393: [
{"DESCRIPTION":"WORK","VALUE":"71111111111"},
{"DESCRIPTION":"WORK","VALUE":"71111111111"}],
1262415: 12,
1256527: 3,
1272573: 817683,
},
"LEADS": [36375665],
"ID": 52627067
}
}
So if you have the following code, it should work:
url = "url"
cookies = {
"csrf_token":"",
"refresh_token":"",
"access_token":""
}
data = {"id": [52626995, 52627067],
"result_element": {
"NAME": "Аркадий",
"MAIN_USER_ID": 8272126,
"TAGS": [559091, 559091],
"cfv": {
664393: [
{"DESCRIPTION":"WORK","VALUE":"71111111111"},
{"DESCRIPTION":"WORK","VALUE":"71111111111"}],
1262415: 12,
1256527: 3,
1272573: 817683,
},
"LEADS": [36375665],
"ID": 52627067
}
}
resp = requests.post(url=url, cookies=cookies, data=data)
return resp
I did it manually. First, check whether I have correctly parsed your string.
Check out the requests documentation
data – (optional) Dictionary, list of tuples, bytes, or file-like object to send in the body of the Request.
So only thing you need is to encode your string to bytes:
resp = requests.post(url=url, cookies=cookies, data=data.encode())
The more detailed explanation is that strings in Python 3 are abstract representation of the characters you see. You can use Czech letter "Ř" in Python regardless what encoding is used to represent the characters as bytes in the computer memory.
However, to send it over internet, you have to send it encoded as bytes.
If you would like to get those bytes, you have to specify the encoding that converts characters to bytes representing them. For Czech, the most appropriate is UTF-8 (as for almost anything) or maybe Windows-1250 aka CP-1250:
>>> x = "Ř"
>>> x
'Ř'
>>> x.encode("utf-8")
b'\xc5\x98'
>>> x.encode("cp1250")
b'\xd8'
Plain str.encode without encoding specified uses UTF-8, probably the best choice:
>>> x.encode()
b'\xc5\x98'
JSON return from spotify api. Example:
{
"tracks": {
"href": "https://api.spotify.com/v1/search?query=Stero+Hearts&type=track&offset=0&limit=1",
"items": [
{
"album": {
"album_type": "album",
"artists": [
{
"external_urls": {
"spotify": "https://open.spotify.com/artist/4IJczjB0fJ04gs4uvP0Fli"
},
"href": "https://api.spotify.com/v1/artists/4IJczjB0fJ04gs4uvP0Fli",
"id": "4IJczjB0fJ04gs4uvP0Fli",
"name": "Gym Class Heroes",
"type": "artist",
"uri": "spotify:artist:4IJczjB0fJ04gs4uvP0Fli"
}
]
}
}
]
}
}
Broken Code
import requests, json
spotifytrack = input("Name of Song?\\n")
link = "https://api.spotify.com/v1/search?q=" + spotifytrack + "&type=track&limit=1"
token = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
header = {
"Authorization": "Bearer {}".format(token),
"Content-Type": "application/json",
"Accept": "application/json",
}
auth_response = requests.get(link, headers=header)
pretty_response = json.dumps(auth_response.json(), indent=4)
data_by_user = {}
for d in auth_response:
data_by_user[d["artist"]] = d
print(data_by_user["uri"])
"""
def find_track_from_json(auth_response, artist):
return [p for p in auth_response if p["artist"] == artist][0]["uri"]
urii = find_track_from_json(auth_response, "uri")
print(urii)
x = load.json(auth_response.json())
print("Here is the data whic we have imported\n")
print(pretty_response)
print(x["name"])
print(x["uri"])
print(x["spotify"])
"""
Errors noticed:
File "spotify.py", line 19, in <module>
data_by_user[d["artist"]] = d
TypeError: byte indices must be integers or slices, not str
The aim is to convert word search to link in a cli application.
I tried load.json which i saw in some website and also tried def.
I expected the program to find out the artist name and uri from the json and print it in the cli interface.
You are iterating over the encoded json string:
auth_response = requests.get(link, headers=header)
for d in auth_response:
Python is complaining that you aren't providing a numerical index, which is correct as auth_response is just a string!
You should call json.loads to decode the string, and then you can iterate over it.
auth_response = requests.get(link, headers=header)
decoded_auth_response = json.loads(auth_response)
data_by_user = {}
for d in decoded_auth_response:
data_by_user[d["artist"]] = d
As you haven't provided the full json output from the API call I'm not sure what data is actually in decoded_auth_response, and you haven't described what your expected output would look like, so you may need to do some more work to find the correct data in each iteration.
The result from requests.get() is a requests.Response object. As far as I can see you want to iterate over the response body which is JSON. The requests.Response object has a .json() method which returns a dict from the response JSON.
Looking at the response you would probably want to iterate over resp_json['tracks']['items'] which is a list.
So to summarize your code should look something like this:
auth_response = requests.get(link, headers=header)
items = auth_response.json()['tracks']['items']
for d in items:
print(d)
I am trying to get the values from objects in the following JSON response:
[
{
"compositionId": "-Mkl92Mii2UF3xzi1q7L",
"compositionName": null,
"mainComposition": true,
"animation": {
"state": "Out1"
}
},
{
"compositionId": "bbbbbb",
"compositionName": null,
"mainComposition": true,
"animation": {
"state": "Out1"
}
}
]
What I would like to get in a loop is all the compositionIds but I don't get the correct output.
I can dump the complete JSON with the following code:
import requests
import json
url = 'http://192.168.1.33/data'
r = requests.get(url)
data = json.loads(r.content.decode())
json_str = json.dumps(data)
resp = json.loads(json_str)
print (resp)
You can simply use the requests module, in fact it does provide a builtin json decoder, that is the .json() function. Done that, you can simply iterate over your json objects with a simple for.
You could do something similar to this:
import requests
url = 'http://192.168.1.33/data'
r = requests.get(url)
my_json_file = r.json()
for json_object in my_json_file:
# Do something with json_object['compoitionId']
pass
Try something like this:
import requests
import json
url = 'http://192.168.1.33/data'
r = requests.get(url)
data = json.loads(r.content.decode())
print([d['compositionId'] for d in data])
I've been digging a hole deeper and deeper trying to work out my api script in python. I'm not sure if i'm just doing something wrong, or i'm misunderstanding the way the projection section is to be written.
Here is the information I'll provide.. So we have two ways to get information from our API through JSON or via socketJS. The socket JS code i will provide down the bottom which essentially does the same thing..
What's going wrong is that it doesn't seem to be processing the parameters correctly, all i get is the same values as i would if i have added no filters or projections.. Does anyone have any ideas on what i'm doing wrong? I suspect i'm not using the requests library correctly, however i have looked and i don't seem to find anything for my particular case in the documentation.
Working SocketJS:
{
"address": "service",
"body": {
"action": "getControlers",
"params": {
"filter": {
"deviceClass": {
"$like" : "*mainControllers*"
}
},
"projection": {
"tagValues": {
"IdMap": 1,
"StateDevice": 1
}
},
"limit":1000
}
}
}
equivalent line via API-Rest outside of Python:
https://URLURL/rest/service/controlers?projection={"tagValues":{"StateDevice": 1}}&filter= {"DeviceClass": {"$like" : "*Controlers*"}}
My script is as follows:
import requests
import json
import os
header = {"Authorization": 'access_token *Iputakeyheretomakethingswork*'}
parameters = {"Filter": {"deviceClass": {"$like" : "*Controller*"}},
"Projection": {"tagValues":{"IdStateMap": 1, "stateDevice": 1}}}
response = requests.get("https://urlgoeshere", headers=header, params=parameters)
print(response.status_code)
data = response.json()
with open('data.txt', 'w') as outfile:
json.dump(data, outfile, sort_keys = True, indent = 4,
ensure_ascii = False)
params does not take a nested dictionary structure. Your API is essentially asking for JSON formatted values in the query string, but you are not providing those.
Moreover, your example URL uses lowercased parameter names, your dictionary contains uppercased parameters.
Instead, requests will convert the any container in params to a string by taking each element, before encoding it with URL encoding. For a dictionary, that means only the keys are used; you are essentially producing the following URL:
>>> import requests
>>> parameters = {"Filter": {"deviceClass": {"$like" : "*Controller*"}},
... "Projection": {"tagValues":{"IdStateMap": 1, "stateDevice": 1}}}
>>> prepped = requests.Request('GET', 'http://example.com/', params=parameters).prepare()
>>> prepped.url
'http://example.com/?Filter=deviceClass&Projection=tagValues'
The following would produce the equivalent of your sample URL:
parameters = {
"filter": '{"deviceClass": {"$like": "*Controller*"}}',
"projection": '{"tagValues": {"IdStateMap": 1, "stateDevice": 1}}'
}
Note that I lowercased the keys and the values are just strings. You could use the json.dumps() function to produce those strings from Python dictionaries if need be:
import json
filter = {"deviceClass": {"$like": "*Controller*"}}
projection = {"tagValues": {"IdStateMap": 1, "stateDevice": 1}}
parameters = {
"filter": json.dumps(filter),
"projection": json.dumps(projection),
}
Demo:
>>> parameters = {
... "filter": '{"deviceClass": {"$like" : "*Controller*"}}',
... "projection": '{"tagValues":{"IdStateMap": 1, "stateDevice": 1}}'
... }
>>> prepped = requests.Request('GET', 'http://example.com/', params=parameters).prepare()
>>> prepped.url
'http://example.com/?filter=%7B%22deviceClass%22%3A+%7B%22%24like%22+%3A+%22%2AController%2A%22%7D%7D&projection=%7B%22tagValues%22%3A%7B%22IdStateMap%22%3A+1%2C+%22stateDevice%22%3A+1%7D%7D'
>>> from urllib.parse import urlparse, parse_qsl
>>> parse_qsl(urlparse(prepped.url).query)
[('filter', '{"deviceClass": {"$like" : "*Controller*"}}'), ('projection', '{"tagValues":{"IdStateMap": 1, "stateDevice": 1}}')]
I'm trying to post the following data. But I'm getting an error. Can you please take look? Thanks a lot.
I'm posting the same data using Postman. And it works.
def _build_post_data(bike_instance):
"""
data = {
"apikey": "XXX",
"data": {
"created_at": "date_XX",
"Price": "Decimal_XX"
}
}
"""
data = {}
raw_data = serializers.serialize('python', [bike_instance])
actual_data = [d['fields'] for d in raw_data]
data.update(
{
"apikey": XXX,
"data": actual_data[0]
}
)
return data
Posting data
bike = Bike.objects.get(pk=XXX)
data = _build_post_data(bike)
dump_data = json.dumps(data, cls=DjangoJSONEncoder)
requests.post(url, data=dump_data)
error
u'{"error":{"message":"422 Unprocessable Entity","errors":[["The data field is required."],["The apikey field is required."]],"status_code":422}}'
data and apikey already in the dict. then why I'm getting an error? Any idea?
Postman works
With Postman you are sending a multipart/form-data request, with requests you only send JSON (the value of the data field in Postman), and are not including the apikey field.
Use a dictionary with the JSON data as one of the values, and pass that in as the files argument. It probably also works as the data argument (sent as application/x-www-urlencoded):
form_structure = {'apikey': 'XXXX', 'data': dump_data}
requests.post(url, files=form_structure)
# probably works too: requests.post(url, data=form_structure)