Reputation: 91
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)
Upvotes: 0
Views: 2177
Reputation: 1124458
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}}')]
Upvotes: 2