How do I pass a variable into a payload - python-3.x

So I have an endpoint that I am trying to integrate in Python which accepts a POST request and according to the API documentation, the payload is to be formatted this way:
payload = "{\r\n\"serviceCode\" : \"V-TV\",\r\n\"type\" : \"DSTV\",\r\n\"smartCardNo\" : \"10441003943\"\r\n}\r\n\r\n\r\n\r\n\r\n"
I want the values of type and smartCardNo to be dynamic, i.e I am going to get the values from a form in the frontend and pass it to the backend but I am finding it difficult to do so.
If I format the payload this way(which of course allows ease of passing variable):
{
"serviceCode": "V-TV",
"type": "DSTV",
"smartCardNo" : "10441003943"
}
I get this error:
{'required_fields': ['The service code field is required.'], 'message': 'Service Code is not supplied', 'status': '301'}
Could anyone tell me how I can pass the values for type and smartCardNo dynamically in the fist format(the format specified in the documentation)....any help will be greatly appreciated.

you can simply use the .format()
dict_values = {
"serviceCode": "V-TV",
"type": "DSTV",
"smartCardNo" : "10441003943"
}
payload = """{{"serviceCode":"{serviceCode}","type":"{mytype}","smartCardNo":"{smartCardNo}"}}""".format(
serviceCode = dict_values["serviceCode"],
mytype = dict_values["type"],
smartCardNo = dict_values["smartCardNo"]
)
output:
'{"serviceCode":"V-TV","type":"DSTV","smartCardNo":"10441003943"}'
If you really need the same format as in your payload example, simple use:
payload = "{{\r\n\"serviceCode\" : \"{serviceCode}\",\r\n\"type\" : \"{mytype}\",\r\n\"smartCardNo\" : \"{smartCardNo}\"\r\n}}\r\n\r\n\r\n\r\n\r\n".format(
serviceCode = dict_values["serviceCode"],
mytype = dict_values["type"],
smartCardNo = dict_values["smartCardNo"]
)
and your output will be:
'{\r\n"serviceCode" : "V-TV",\r\n"type" : "DSTV",\r\n"smartCardNo" : "10441003943"\r\n}\r\n\r\n\r\n\r\n\r\n'

Related

how to send bson.M data in python

i have an Api function in Golang that receive a json data and good working with postman
but i want te call api with python3 but error in parse body
this is my golang code:
var approve bson.M
err := c.BodyParser(&approve)
and this is my data in patch api :
{
"result" : true
}
and this is my python script:
jsondata = bson.BSON.encode({'result': True})
options = CodecOptions(document_class=collections.OrderedDict)
#decoded_doc = bson.BSON(jsondata).decode(codec_options=options)
decoded_doc = bson.decode(jsondata, codec_options=options)
r = requests.patch(approvurl,data=decoded_doc,headers={'Content-Type':'application/json','Authorization':API_KEY,'Imei':'1234567890','phone':'123456789','email':'test#gmail.com'} )
and my backend in my golang throw this exeption :
expected { character for map value
and i compare json object in wirshark :
this is for postman:
enter image description here
and
this is for my python script
enter image description here
please help me to solve my problem in python script
I think what's happening is that you're passing a Python dict using requests.patch's data parameter, which expects a string. It looks like you want to send JSON, so you should use the json parameter (which adds the application/json Content-Type automatically).
Also, it looks like you're encoding a Python dict to BSON format, only to re-decode it back to a Python dict again. Unless I'm missing something, you shouldn't need to do that.
So your Python script can be changed to a single call to requests.patch:
r = requests.patch(
approvurl,
json={'result': True},
headers={'Authorization': API_KEY, ...},
)
my problem solved by added a new function that check agent :
userAgent := string(c.Context().UserAgent())
//print("userAgent=", userAgent)
if strings.HasPrefix(userAgent, "python-requests") {
eq := c.Body() //("result")
if string(eq) == "result=True" {
print("jsonBody is", string(eq))
id, _ := primitive.ObjectIDFromHex(c.Params("id"))
print("Approving started=", true)
tnx`

Storing a specific part of a dict value into a string

import requests
import json
url = "********"
payload = json.dumps({
"username": "*****",
"password": "*****"
})
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
#*** Convert response into a dictionary ***
r = json.loads(response.text)
# *** print the value of they key 'accessToken'
bearerToken = r['accessToken']
print(bearerToken)
Output
{'accessToken': 'e************************************', 'tokenType': 'Bearer'}
What am I trying to achieve?
Grab only the censored code after 'accessToken' and store the new Access Token in a string to use it in HTTP requests.
Note: 'accessToken' is a value of another key called accessToken. So the traditional method of printing the value of the key has already been used in the output shown above.
Complete output:
{
"accessToken" : {
"accessToken" : "e******************",
"tokenType" : "Bearer"
},
"refreshToken" : {
"id" : "6*************",
"lastAccessedTime" : 1***********,
"refreshToken" : "e*************"
}
}
In Python, you can use substrings to accomplish what you want. If the length of the prefix is constant, then all you would need to do is use a slice with constant index,
In your example, it looks like you have an accessToken key, and inside that key is another dictionary holding a key that can change between entries. Assuming that you want the censored portion after e in accessToken, you can access that using:
bearerToken = r['accessToken'][accessToken][1:]
This will give you the access token "******************", which is everything from index 1 onwards. If you just want the entire string, you can omit the [1:] portion.
The solution was to edit the code provided by yeeshue99, the 2nd value to 'accessToken' with the '' marks. the [1:] was also not needed.
Solution
bearerToken = r['accessToken']['accessToken']

CDON API RESTful Api GET request

I'm currently working on fetching customer data from cdon, it's an e-commerce platform. They have their API documentation here:
CDON Api Docu
First let me show you my code:
myToken = '<token here>'
myUrl = 'https://admin.marketplace.cdon.com/api/reports/d8578ef8-723d-46cb-bb08-af8c9b5cca4c'
head = {'Authorization': 'token {}'.format(myToken),
'Status':'Online',
'format':'json'}
filters = '?filter={"Status":["Online"],"format": ["json"] }}'
response = requests.get(myUrl + filters, headers=head)
report = response.json()
print(report.products)
This is returning only the parameters. like for example at at this JSON: CDON Github
Status has a value Online this online is a group of itemsthat I only want to get.
What I'm trying to get is a response like this:
{
"Products": [
{
"SKU": "322352",
"Title": "Fabric Cover",
"GTIN": "532523626",
"ManufacturerArticleNumber": "",
"StatusCDON": "Online",
"ExposeStatusCDON": "Buyable",
"InStock": 0,
"InStockCDON": 0,
"CurrentPriceSE": null,
"OrdinaryPriceSE": null,
"CurrentPriceCDONSE": 299.0000,
"OrdinaryPriceCDONSE": null,
"CurrentPriceDK": null,
"OrdinaryPriceDK": null,
"CurrentPriceCDONDK": null,
"OrdinaryPriceCDONDK": null,
"CurrentPriceNO": null,
"OrdinaryPriceNO": null,
"CurrentPriceCDONNO": null,
"OrdinaryPriceCDONNO": null,
"CurrentPriceFI": null,
"OrdinaryPriceFI": null,
"CurrentPriceCDONFI": null,
"OrdinaryPriceCDONFI": null
},
Which means the full list of the items that are Online
How should I put this... among all the API's I tried this one is very confusing, is this even RestFul? If I can achieve the python equivalent of this C# sample code:
public string Post(Guid repordId, string path)
{
var filter = new JavaScriptSerializer().Serialize(new
{
States = new[] { "0" } // Pending state
});
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair("ReportId", repordId.ToString()),
new KeyValuePair("format", "json"),
new KeyValuePair("filter", filter)
});
var httpClient = new HttpClient() { BaseAddress = new Uri("https://admin.marketplace.cdon.com/") };
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("api", ApiKey);
var response = httpClient.PostAsync(path, content).Result;
response.EnsureSuccessStatusCode();
return response.Content.ReadAsStringAsync().Result;
}
I may be able to undestand how this API works, the response that I got was taken manually from their report function in JSON format.
Image
I made many attempts and at that code ( my code ) I stopped, being on this for 4 hours made me give up and ask. Trust that I have searched as many references as I could. It's really confusing.
How do I get the response that I want? Filtering via url? or via header? is this even restful? Help T_T
The documentation states in the first line, emphasis mine:
In order to generate a report you perform a POST call to the reports API with the parameters you wish to use for the report.
Your Python code does not make a POST request, you are trying a GET request. The documentation goes on
[...] to filter on Swedish orders you set the CountryCodes
attribute to “Sweden” and to get returned and cancelled orders you set
the States attribute to 2 and 3. So in the end the filter would look
like this:
{
"CountryCodes": [ "Sweden" ],
"States": ["2", "3"]
}
So you need to prepare a filter object (a dictionary in Python) with the filters you want. Luckily the Python syntax for dictionaries is equivalent (Python is flexible and also allows single-quoted strings):
filter = {
'CountryCodes': [ 'Sweden' ],
'States': [ '0' ]
}
The documentation goes on
You then post the parameters as form data (content-type:
application/x-www-form-urlencoded) so the request body would look like
this:
ReportId=d4ea173d-bfbc-48f5-b121-60f1a5d35a34&format=json&filter={"CountryCodes":["Sweden"],"States":["2","3"]}
application/x-www-form-urlencoded is the default for HTTP post, the requests module knows that and does this for you automatically. All you need to do is to prepare a data dict which will contain the data you want to post.
data = {
'ReportId': 'd4ea173d-bfbc-48f5-b121-60f1a5d35a34',
'format': 'json'
'filter': json.dumps(filter)
}
The filter parameter is supposed to be in JSON format. You must encode that yourself via json.dumps().
import json
head = { ... as above }
filter = { ... as above }
data = { ... as above }
response = requests.post(url, data, header=head)
I'll leave figuring out setting the Authorization header properly as an exercise for you. Partly because it isn't hard, partly because I have no intention of creating an API key with this website just for testing this and partly because it's entirely possible that your current header already works.

Getting specific keys from dictionaries

I am developing an API service for my website. The website is about Recipes, where a user is supposed to register on his first visit, then log in. When he logs in he gets an access token, which he uses to do REST services on categories and recipes.
So coming to Recipes, he can give a title, ingredients, and directions. Example:
{
"title" : "api recipe",
"directions" : "Testing api recipe directions",
"ingredient1" : "postman",
"ingredient2" : "ing2",
"ingredient3" : "me",
"ingredient4" : "ingredient4",
"ingredient5" : "ingredient5"
}
Now, I am facing a problem when it comes to PUT method. I want to enable a user to edit a recipe giving only that which he wants to edit. Example:
{
"title" : "PUT"
}
Using PUT method, if a user provides an ingredient as such:
{
"ingredient2" : "Potatoes",
"ingredient5" : "stackexchange"
}
I would like to only change the ingredients that he provided me with and leave the rest the way it is.
Before coming to my question, when a user provides the above, I get a dictionary with the keys and values he/she has provided. My question is, how can I get all the ingredients he wants to edit plus their number?
my code:
data = request.get_json()
category = Category.query.filter_by(user_id=user_id).filter_by(id=category_id).first()
if not category:
return jsonify({'message' : 'category does not exists'})
category.edit_recipe(data, id=recipe_id)
return jsonify({'message' : 'Edited successfully'})
def edit_recipe(self, data, *args, **kwargs):
edit_this = None
if 'id' in kwargs:
edit_this = Recipe.query.filter_by(id=kwargs['id']).filter_by(category_id=self.id).first()
else:
edit_this = Recipe.query.filter_by(title=kwargs['prev_title']).filter_by(category_id=self.id).first()
"""TODO: Get ingredient from data followed by its number.
if data == {'title' = 'change title', 'ingredient2' = 'change ing 2', 'ingredient5' = 'change ing 5'}
then I want to get keys that start with ingredient followed by their number and its value
"""
if 'title' in data:
edit_this.title = data['title']
if 'directions' in data:
edit_this.directions = data['directions']
if 'filename' in data:
edit_this.filename = data['filename']
db.session.commit()
To get only the ingredients, the following below should
keyValue = {
"title" : "api recipe",
"directions" : "Testing api recipe directions",
"ingredient1" : "postman",
"ingredient2" : "ing2",
"ingredient3" : "me",
"ingredient4" : "ingredient4",
"ingredient5" : "ingredient5"
}
oldListOfKeys = keyValue.keys()
ingredientsList = filter(lambda x: x not in ["directions", "title"], oldListOfKeys)
newDict = {key: keyValue[key] for key in keyValue if key in ingredientsList}
print newDict # {'ingredient4': 'ingredient4', 'ingredient5': 'ingredient5', 'ingredient1': 'postman', 'ingredient2': 'ing2', 'ingredient3': 'me'}
(Am using this in a flask app with sqlAlchemy- hope it helps)
In your put method, first query of a specific recipe for example
recipe = Recipe.query.filter_by(recipe_id=id).first()
Then you can access the specific keys like this
data = request.get_json()
recipe.title = data['title']
recipe.directions = data['directions']
recipe.ingredient1 = data['ingredient1']
recipe.ingredient2 = data['ingredient2']

node.js - Is there any proper way to parse JSON with large numbers? (long, bigint, int64)

When I parse this little piece of JSON:
{ "value" : 9223372036854775807 }
This is what I get:
{ hello: 9223372036854776000 }
Is there any way to parse it properly?
Not with built-in JSON.parse. You'll need to parse it manually and treat values as string (if you want to do arithmetics with them there is bignumber.js) You can use Douglas Crockford JSON.js library as a base for your parser.
EDIT2 ( 7 years after original answer ) - it might soon be possible to solve this using standard JSON api. Have a look at this TC39 proposal to add access to source string to a reviver function - https://github.com/tc39/proposal-json-parse-with-source
EDIT1: I created a package for you :)
var JSONbig = require('json-bigint');
var json = '{ "value" : 9223372036854775807, "v2": 123 }';
console.log('Input:', json);
console.log('');
console.log('node.js bult-in JSON:')
var r = JSON.parse(json);
console.log('JSON.parse(input).value : ', r.value.toString());
console.log('JSON.stringify(JSON.parse(input)):', JSON.stringify(r));
console.log('\n\nbig number JSON:');
var r1 = JSONbig.parse(json);
console.log('JSON.parse(input).value : ', r1.value.toString());
console.log('JSON.stringify(JSON.parse(input)):', JSONbig.stringify(r1));
Output:
Input: { "value" : 9223372036854775807, "v2": 123 }
node.js bult-in JSON:
JSON.parse(input).value : 9223372036854776000
JSON.stringify(JSON.parse(input)): {"value":9223372036854776000,"v2":123}
big number JSON:
JSON.parse(input).value : 9223372036854775807
JSON.stringify(JSON.parse(input)): {"value":9223372036854775807,"v2":123}
After searching something more clean - and finding only libs like jsonbigint, I just wrote my own solution. Is not the best, but it solves my problem. For those that are using Axios you can use it on transformResponse callback (this was my original problem - Axios parses the JSON and all bigInts cames wrong),
const jsonStr = `{"myBigInt":6028792033986383748, "someStr":"hello guys", "someNumber":123}`
const result = JSON.parse(jsonStr, (key, value) => {
if (typeof value === 'number' && !Number.isSafeInteger(value)) {
let strBig = jsonStr.match(new RegExp(`(?:"${key}":)(.*?)(?:,)`))[1] // get the original value using regex expression
return strBig //should be BigInt(strBig) - BigInt function is not working in this snippet
}
return value
})
console.log({
"original": JSON.parse(jsonStr),
"handled": result
})
A regular expression is difficult to get right for all cases.
Here is my attempt, but all I'm giving you is some extra test cases, not the solution. Likely you will want to replace a very specific attribute, and a more generic JSON parser (that handles separating out the properties, but leaves the numeric properties as strings) and then you can wrap that specific long number in quotes before continuing to parse into a javascript object.
let str = '{ "value" : -9223372036854775807, "value1" : "100", "strWNum": "Hi world: 42 is the answer", "arrayOfStrWNum": [":42, again.", "SOIs#1"], "arrayOfNum": [100,100,-9223372036854775807, 100, 42, 0, -1, 0.003] }'
let data = JSON.parse(str.replace(/([:][\s]*)(-?\d{1,90})([\s]*[\r\n,\}])/g, '$1"$2"$3'));
console.log(BigInt(data.value).toString());
console.log(data);
you can use this code for change big numbers to strings and later use BigInt(data.value)
let str = '{ "value" : -9223372036854775807, "value1" : "100" }'
let data = JSON.parse(str.replace(/([^"^\d])(-?\d{1,90})([^"^\d])/g, '$1"$2"$3'));
console.log(BigInt(data.value).toString());
console.log(data);

Resources