Python JSON nested key value pair parsing - python

I am trying to make api call which has json as value to one of the keys. It is failing because of extra double quotes in inner json formed.
variable = request.GET.get('name', '{}')
This value of variable is json that is passed from webpage.
Sample data in variable will be like:-
variable= {'name': 'ABC', 'Id': '1'}
Now when I try to form my payload to be sent in post call,
payload = {
'var1': var1,
'variable': variable,
}
Now this "variable" which is added to payload is treated as String and append with double quotes, like this:-
{'var1': '130', 'variable': "{'name': 'ABC', 'Id': '1'}"}
But I want it to be like this:-
{'var1': '130', 'variable': {'name': 'ABC', 'Id': '1'}}
Any suggestions how to make it possible?
this is the code to make the post call with data:-
r = requests.post("URL",data= json.dumps(payload),headers={'Authorization': obj.header, 'Content-type': 'application/json'}, proxies=getProxyDict())

When you get variable from the request it isn't just 'treated' as a string... is is a string.
So you need to:
json.loads(variable)
before adding it to the dict which is later serialized to json.
i.e.
variable = json.loads(request.GET.get('name', '{}'))
payload = {
'var1': var1,
'variable': variable,
}
r = requests.post("URL",data= json.dumps(payload),headers={'Authorization': obj.header, 'Content-type': 'application/json'}, proxies=getProxyDict())

You have presumably already dumped variable to a JSON string. Don't do that; leave it as a dict, and dump the whole thing in one go.

import json
variable = {'name': 'ABC', 'Id': '1'}
payload = {
'var1': 'foo',
'variable': variable,
}
print json.dumps(payload, indent=4)
results to
{
"variable": {
"name": "ABC",
"Id": "1"
},
"var1": "foo"
}
which is perfectly json. But, you may need to set your headers according to the API you're talking to.
request = requests.get('myurl', headers={'accept': 'application/json'})
json_data = request.json()
# manipulate json_data
request = requests.post('myurl', headers={'content-type': 'application/json'}, json=json_data)

Few things I would like to point here.
variable= "{'name': 'ABC', 'Id': '1'}"
This is NOT a valid json string.
variable= '{"name": "ABC", "Id": "1"}'
This is a valid json string.
So first before attaching this variable to payload dict you need to convert it to a python dict like this.
variable = json.loads(variable)
This will create variable something like this.
{u'name': u'ABC', u'Id': u'1'}
Now you can go ahead and add this to your payload dict and continue what you are doing.

Related

interpolating variable to a complex string in python

I have a variable group_array like this
groups_array=[{"group": "18652_PDR"}, {"group": "11262_PDR"}, {"group": "3787_PDR"}, {"group": "4204_PDR"}]
I want to put the groups_array variable inside below string so I tried like this using the f method
data = f'{"request":{"streaming_type":"quote", "data":{"groups": {groups_array}}, "request_type":"subscribe", "response_format":"json"}}'
But am getting error deeply nested error
I want the string to be in below format after adding the variable
data = '{"request":{"streaming_type":"quote", "data":{"groups": [{"group": "18652_PDR"}, {"group": "11262_PDR"}, {"group": "3787_PDR"}, {"group": "4204_PDR"}]}, "request_type":"subscribe", "response_format":"json"}}'
Could someone tell me how can I properly do it in this case as there are too many "" and {}?
You can just use the built-in json package. You would create a dictionary of your data and pass it to json.dumps to receive the json string.
import json
groups_array = [{"group": "18652_PDR"}, {"group": "11262_PDR"}, {"group": "3787_PDR"}, {"group": "4204_PDR"}]
data = {"request":
{"streaming_type": "quote",
"data": {
"groups": groups_array
},
"request_type": "subscribe",
"response_format": "json"
}
}
data_json = json.dumps(data)
print(data)
# Output:
{'request': {'streaming_type': 'quote', 'data': {'groups': [{'group': '18652_PDR'}, {'group': '11262_PDR'}, {'group': '3787_PDR'}, {'group': '4204_PDR'}]}, 'request_type': 'subscribe', 'response_format': 'json'}}
You can assign directly to dict and create a json (stringify it) if your request needs string:
import json
data = json.dumps({"request":{"streaming_type":"quote", "data":{"groups": groups_array}, "request_type":"subscribe", "response_format":"json"}})
Or if dictionary is also an option - pass it without json.dumps

How to create a json from the json as function

Need to create a function to extract values from the json. after that i need to parse the so many similar type of json and save in to file.
json is below
j = '''{
"action": "post",
"status": "completed",
"result": {
"country": "usa",
"is_allow": 'true',
"advance details": {
"value": 'true'
}
}
}'''
convert to json
k = eval(json.dumps(m))
{'action': 'post',
'status': 'completed',
'result': {'country': 'usa',
'is_allow': 'true',
'advance details': {'value': 'true'}}}
Expected out
{'is_allow': 'true','value': 'true'}
pseudo code
Disclaimer : please don't do m['result']['is_allow'] because i need as function to pass so many json
When working with json in python, it should be deserialized into a python object, like a dict, or list; it's weird think to create a function that is 'generic' to any key you want to get, it's just the __getitem__ of dict, if you think to export thing into function, be more specific like this:
def get_is_allow_and_value(my_data):
result = {}
result['is_allow'] = my_data['result']['is_allow']
result['value'] = my_data['result']['advance details']['value']
return result
Also don't use eval you can simple use json.loads for this

Massage data in a dict with array of json objects (nested data/data in a tree structure) in Python 3.0

I need to store the value of 'Address' in a variable for later use. The 'address' value is deep inside an output from a json.dump.
From what I've gathered over looking through some similar issues is that I need to iterate between each value in order access the ScriptPubKey (dict). Since I am only a few hours in to Python, without much prior knowledge about programming, I'm sure that I'm missing something simple - or completely misunderstand the task at hand.
for x in response['result']['vout']:
for y in x:
print(y)
So this is the part of the program I am having issues with:
###Function
def gettranshash(transhashen):
payload = {
"method": "getrawtransaction",
"params": [transhashen],
}
response = requests.post(url, data=json.dumps(payload), headers=headers).json()
response = response['result']
payload = {
"method": "decoderawtransaction",
"params": [response],
}
response = requests.post(url, data=json.dumps(payload), headers=headers).json()
return response
###How I access the function in my program
transaktionshash = input("write transactionhash for a block: ")
response = gettranshash(transaktionshash)
print("Blocket: ", response['result']['hash'])
###Missing the address output :(
print("Blocket: ", response['result']['vout'])
Result from response:
{'result': {'txid':
'4d879b24d65dd418a8e806ed69df7f170022e89666590a7b08e0095009865a5b',
'hash':
'4d879b24d65dd418a8e806ed69df7f170022e89666590a7b08e0095009865a5b',
'version': 1, 'size': 87, 'vsize': 87, 'locktime': 0, 'vin':
[{'coinbase': '0163', 'sequence': 4294967295}], 'vout': [{'value': 50.0,
'n': 0, 'scriptPubKey': {'asm': 'OP_DUP OP_HASH160
071e31b8289aa9d80b970230cb1b8b76466f2ec4 OP_EQUALVERIFY OP_CHECKSIG',
'hex': '76a914071e31b8289aa9d80b970230cb1b8b76466f2ec488ac', 'reqSigs':
1, 'type': 'pubkeyhash', 'addresses':
['1eduGsrvBJcfyTMij2rYXk9viiVV78PNq']}}]}, 'error': None, 'id': None}
This is the result from response['result']['vout']:
[{'value': 50.0, 'n': 0, 'scriptPubKey': {'asm': 'OP_DUP OP_HASH160
071e31b8289aa9d80b970230cb1b8b76466f2ec4 OP_EQUALVERIFY OP_CHECKSIG',
'hex': '76a914071e31b8289aa9d80b970230cb1b8b76466f2ec488ac', 'reqSigs':
1,
'type': 'pubkeyhash', 'addresses':
['1eduGsrvBJcfyTMij2rYXk9viiVV78PNq']}}]
this is from the documentation:
"vout" : [ (array of json objects)
{
"value" : x.xxx, (numeric) The value in BTC
"n" : n, (numeric) index
"scriptPubKey" : { (json object)
"asm" : "asm", (string) the asm
"hex" : "hex", (string) the hex
"reqSigs" : n, (numeric) The required sigs
"type" : "pubkeyhash", (string) The type, eg
'pubkeyhash'
"addresses" : [ (json array of string)
"address" (string) bitcoin address
,...
]
}
}
,...
],
So basically; I need to access the 'address' value in order to use it as input in an iteration for a different function.
Many thanks for any potential tips and let me know if I need to add additional information or clarify anything:)

How to send urlencoded parameters in POST request in python

I'm trying to deploy my production ready code to Heroku to test it. Unfortunately, it is not taking JSON data so we converted into x-www-form-urlencoded.
params = urllib.parse.quote_plus(json.dumps({
'grant_type': 'X',
'username': 'Y',
'password': 'Z'
}))
r = requests.post(URL, data=params)
print(params)
It is showing an error in this line as I guess data=params is not in proper format.
Is there any way to POST the urlencoded parameters to an API?
You don't need to explicitly encode it, simply pass your dict to data argument and it will be encoded automatically.
>>> r = requests.post(URL, data = {'key':'value'})
From the official documentation:
Typically, you want to send some form-encoded data — much like an HTML
form. To do this, simply pass a dictionary to the data argument. Your
dictionary of data will automatically be form-encoded when the request
is made
Set the Content-Type header to application/x-www-form-urlencoded.
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
r = requests.post(URL, data=params, headers=headers)
Just to an important thing to note is that for nested json data you will need to convert the nested json object to string.
data = { 'key1': 'value',
'key2': {
'nested_key1': 'nested_value1',
'nested_key2': 123
}
}
The dictionary needs to be transformed in this format
inner_dictionary = {
'nested_key1': 'nested_value1',
'nested_key2': 123
}
data = { 'key1': 'value',
'key2': json.dumps(inner_dictionary)
}
r = requests.post(URL, data = data)

String format a JSON string gives KeyError

Why does this code give a KeyError?
output_format = """
{
"File": "{filename}",
"Success": {success},
"ErrorMessage": "{error_msg}",
"LogIdentifier": "{log_identifier}"
}
"""
print output_format.format(filename='My_file_name',
success=True,
error_msg='',
log_identifier='123')
Error message:
KeyError: ' "File"'
You need to double the outer braces; otherwise Python thinks { "File".. is a reference too:
output_format = '{{ "File": "{filename}", "Success": {success}, "ErrorMessage": "{error_msg}", "LogIdentifier": "{log_identifier}" }}'
Result:
>>> print output_format.format(filename='My_file_name',
... success=True,
... error_msg='',
... log_identifier='123')
{ "File": "My_file_name", "Success": True, "ErrorMessage": "", "LogIdentifier": "123" }
If, indicentally, you are producing JSON output, you'd be better off using the json module:
>>> import json
>>> print json.dumps({'File': 'My_file_name',
... 'Success': True,
... 'ErrorMessage': '',
... 'LogIdentifier': '123'})
{"LogIdentifier": "123", "ErrorMessage": "", "Success": true, "File": "My_file_name"}
Note the lowercase true in the output, as required by the JSON standard.
As mentioned by Tudor in a comment to another answer, the Template class was the solution that worked best for me. I'm dealing with nested dictionaries or list of dictionaries and handling those were not as straightforward.
Using Template though the solution is quite simple.
I start with a dictionary that is converted into a string. I then replace all instances of { with ${ which is the Template identifier to substitute a placeholder.
The key point of getting this to work is using the Template method safe_substitute. It will replace all valid placeholders like ${user_id} but ignore any invalid ones that are part of the dictionary structure, like ${'name': 'John', ....
After the substitution is done I remove any leftovers $ and convert the string back to a dictionary.
In the code bellow, resolve_placeholders returns a dictionary where each key matches a placeholder in the payload string and the value is substituted by the Template class.
from string import Template
.
.
.
payload = json.dumps(payload)
payload = payload.replace('{', '${')
replace_values = self.resolve_placeholders(payload)
if replace_values:
string_template = Template(payload)
payload = string_template.safe_substitute(replace_values)
payload = payload.replace('${', '{')
payload = json.loads(payload)
To extend on Martijn Pieters answer and comment:
According to MArtijn' comment, escaping the {..} pairs that are not placeholders is they way to go with nested dictionaries. I haven't succeded in doing that, so I suggest the following method.
For nested dictionaries I tried doubling up on any { and } of the nested dictionaries.
a='{{"names":{{"a":"{name}"}}}}'
a.format(name=123) output:
output: '{"names":{"a":"123"}}'
But this makes using format to change values inside a json string, a over-complex method, so I use a twist on the format command.
I replace ${param_name} in a json string. For example:
My predefined JSON looks like this:
my_json_dict = {
'parameter': [
{
'name': 'product',
'value': '${product}'
},
{
'name': 'suites',
'value': '${suites}'
},
{
'name': 'markers',
'value': '${markers}'
}
]
}
I provide this dictionary as values to replace instead of the parameters
parameters = {
'product': 'spam',
'suites': 'ham',
'markers': 'eggs'
}
And use this code to do the replacment
json_str = json.dumps(my_json_dict)
for parameter_name, parameter_value in parameters.iteritems():
parameter_name = '${'+parameter_name+'}'
json_str = json_str.replace(parameter_name, parameter_value)
json_dict = json.loads(json_str)

Categories