Formatting JSON data in Python - python

I am sending JSON data over post method to one of my ML models, the problem is
it is not able to pick which object to fetch for fields.
Below is the sample JSON
{
"a": {
"asD": 1553990400000,
"cust": "S65A00",
"party": "1234",
"custS": null,
"sngldt: 1557014400000,
},
"b": {
"History": [],
"cust": "S65A00",
"mb_cntry": "US",
"mbdt": 1490918400000,
"mbsg_dt": 1553904000000,
}
}
How Can I Merge this JSON in the ML Code in single braces like below, I don't have the luxury to format the JSON itself during Post request.
{
"asD": 1553990400000,
"cust": "S65A00",
"party": "1234",
"custS": null,
"sngldt: 1557014400000,
"History": [],
"mb_cntry": "US",
"mbdt": 1490918400000,
"mbsg_dt": 1553904000000,
}
Below is the code that I have tried but failing
#app.route('/', methods=['GET', 'POST'])
def execute():
if request.method == 'POST':
json_data = request.get_json()
batch=json.dumps(json_data)
dataFrame = pd.DataFrame(json_data)
print(len(dataFrame.columns))
df=pd.melt(dataFrame,id_vars=[' ','b'], value_name='values')
print(df)

merged = dict()
merged.update(obj.a)
merged.update(obj.b)

With unpacking syntax:
...
json_data = dict(json_data['a'], **json_data['b'])
print(json_data)
prints:
{'asD': 1553990400000, 'cust': 'S65A00', 'party': '1234', 'custS': 'null', 'sngldt': 1557014400000, 'History': [], 'mb_cntry': 'US', 'mbdt': 1490918400000, 'mbsg_dt': 1553904000000}

Related

How to remove double quote from key value in dictionary

I have this payload:
"cardType": "CHOICE",
"step": 40,
"title": {"en-GB": "YOUR REPORT"},
"description": {"en-GB": ""},
"options": [
{"optionId": 0, "text": {"en-GB": "Ask me"}},
{"optionId": 1, "text": {"en-GB": "Phone a nurse"}},
{"optionId": 2, "text": {"en-GB": "Download full report"}},
],
"_links": {
"self": {
"method": "GET",
"href": "/assessments/898d915e-229f-48f2-9b98-cfd760ba8965",
},
"report": {
"method": "GET",
"href": "/reports/17340f51604cb35bd2c6b7b9b16f3aec",
},
},
}
I then url encode it like so and redirect to a report view:
url = reverse("my-reports")
reverse_url = encodeurl(data, url)
The urlencode output is returned as this:
"/api/v2/ada/reports?cardType=CHOICE&step=40&title="
"%7B%27en-GB%27%3A+%27YOUR+REPORT%27%7D&description="
"%7B%27en-GB%27%3A+%27%27%7D&options="
"%5B%7B%27optionId%27%3A+0%2C+%27text%27%3A+%7B%27en-GB"
"%27%3A+%27Ask+me%27%7D%7D%2C+%7B%27optionId%27%"
"3A+1%2C+%27text%27%3A+%7B%27en-GB%27%3A+%27Phone+a+nurse"
"%27%7D%7D%2C+%7B%27optionId%27%3A+2%2C+%27text%27%3A+%7B"
"%27en-GB%27%3A+%27Download+full+report%27%7D%7D%5D&_links="
"%7B%27self%27%3A+%7B%27method%27%3A+%27GET%27%2C+%27href%27%"
"3A+%27%2Fassessments%2F898d915e-229f-48f2-9b98-cfd760ba8965"
"%27%7D%2C+%27report%27%3A+%7B%27method%27%3A+%27GET%27%"
"2C+%27href%27%3A+%27%2Freports%2F"
"17340f51604cb35bd2c6b7b9b16f3aec%27%7D%7D"
In my report view I get the payload from the url query string:
class Reports(generics.GenericAPIView):
permission_classes = (permissions.AllowAny,)
def get(self, request, *args, **kwargs):
result = request.GET
data = result.dict()
print(data)
Now the problem is that the output of the transferred data which is printed above has quotes for nested keys.
{
'cardType': 'CHOICE',
'step': '40', 'title': "{'en-GB': 'YOUR REPORT'}",
'description': "{'en-GB': ''}",
'options': "[{'optionId': 0,
'text': {'en-GB': 'Ask me'}},
{'optionId': 1, 'text': {'en-GB': 'Phone a nurse'}}, {'optionId': 2, 'text': {'en-GB': 'Download full report'}}]",
'_links': "{'self': {'method': 'GET', 'href': '/assessments/898d915e-229f-48f2-9b98-cfd760ba8965'}, 'report': {'method': 'GET', 'href': '/reports/17340f51604cb35bd2c6b7b9b16f3aec'}}"
}
Notice the double quote in the "description", "options" keys etc.
Is there a way to remove this or pass this across to the view so that when I unwrap it I have the same data I started with.
Thanks
import urllib.parse
import json
# convert your dict to a string
json_string = json.dumps(your_payload)
# urlencode the json string
encoded = urllib.parse.quote(json_string.encode('utf-8'))
# build the url
url = reverse("my-reports")
reverse_url = f"{url}?payload={encoded}"
Then in your view:
class Reports(generics.GenericAPIView):
permission_classes = (permissions.AllowAny,)
def get(self, request, *args, **kwargs):
payload = request.GET.get('payload')
# do the encoding process in reverse
urldecoded = urllib.parse.unquote(payload)
data = json_loads(urldecoded)
print(data)

How can I maintain the headers for my JSON data after aggregation?

I am developing a REST API in mongoDB with pymongo. I have several endpoints to execute different queries. I want the JSON data created to maintain the headers it had in the original JSON file.
This is the original JSON data.
"player": "Jamie Vardy", "team": "Leicester City", "assists": 5,
After my endpoint is executed the data returned looks like this:
5,
"Jamie Vardy",
"Leicester City",
The endpoint:
#app.route("/api/v1.0/players/top-assister", methods=["GET"])
def top_assister():
pipeline = [ { "$match" : { "assists" : {"$gte" : 12} } },
{ "$project" : {"assists" : 1, "player" : 1, "team":1}}
]
top_assister = []
for player in players.aggregate(pipeline):
player["assists"]
str(player["player"])
str(player["team"])
top_assister.append([player["assists"], str(player["player"]), str(player["team"])])
return make_response(jsonify(top_assister), 200)

copying data from json response [Python]

I have a scenario where I am trying to extract data from json response which is obtained from the GET request and then rebuilding the json data by changing some values and then sending a PUT request at same time after rebuilding the json data(i.e, after changing idter value)
below is the target json response.
target_json = {
"name": "toggapp",
"ts": [
1234,
3456
],
"gs": [
{
"id": 4491,
"con": "mno"
},
{
"id": 4494,
"con": "hkl"
}
],
"idter": 500,
"datapart": false
}
from the above json I am trying to change the idter value to my custom value and rebuild it into json data again and post the new json data.
Here is what I have tried :
headers = {'Authorization': 'bearer ' + auth_token, 'Content-Type':'application/json', 'Accept':'application/json'}
tesstid =[7865, 7536, 7789]
requiredbdy = []
for key in testid:
get_metadata_targetjson= requests.get('https://myapp.com/%s' %key, headers = headers)
metadata=get_metadata_target.json()
for key1 in metadata:
requiredbdy.append(
{
"metadata" : [{
"name": key1['name'],
"ts": key1['ts'],
"gs": key1[gs],
"idter": 100, #custom value which I want to change
"datapart": false
} ]
}
)
send_metadata_newjson= requests.put('https://myapp.com/%s' %key, headers = headers data = requiredbdy)
print(send_metadata_newjson.status_code)
Is this approach fine or How do I proceed in order to achieve this scenario.
You can use the built-in json module for this like so
import json
my_json = """
{
"name": "toggapp",
"ts": [
1234,
3456
],
"gs": [
{
"id": 4491,
"con": "mno"
},
{
"id": 4494,
"con": "hkl"
}
],
"idter": 500,
"datapart": false
}
"""
json_obj = json.loads(my_json)
json_obj['idter'] = 600
print(json.dumps(json_obj))
Prints
{"name": "toggapp", "ts": [1234, 3456], "gs": [{"id": 4491, "con": "mno"}, {"id": 4494, "con": "hkl"}], "idter": 600, "datapart": false}
There's this small script used it to find entries in some very long and unnerving JSONs. not very beautifull und badly documented but maybe helps in your scenario.
from RecursiveSearch import Retriever
def alter_data(json_data, key, original, newval):
'''
Alter *all* values of said keys
'''
retr = Retriever(json_data)
for item_no, item in enumerate(retr.__track__(key)): # i.e. all 'value'
# Pick parent objects with a last element False in the __track__() result,
# indicating that `key` is either a dict key or a set element
if not item[-1]:
parent = retr.get_parent(key, item_no)
try:
if parent[key] == original:
parent[key] = newval
except TypeError:
# It's a set, this is not the key you're looking for
pass
if __name__ == '__main__':
alter_data(notification, key='value',
original = '********** THIS SHOULD BE UPDATED **********',
newval = '*UPDATED*')

How to convert python-request JSON results to csv?

I am trying to get my list of contacts from my WIX website using their API endpoint url and the requests module in python. I am totally stuck.
Here's my code so far:
import requests
auth_key = "my auth key"
r = requests.get("https://www.wixapis.com/crm/v1/contacts", headers={"Authorization": auth_key})
print(r.status_code)
dict = r.json()
contacts_list = dict["contacts"]
for i in contacts_list:
for key in i:
print(key, ':', i[key])
Here is what I get:
200
id : long id string 1
emails : [{'tag': 'UNTAGGED', 'email': 'sampleemail1#yahoo.com'}]
phones : []
addresses : [{'tag': 'UNTAGGED', 'countryCode': 'US'}]
metadata : {'createdAt': '2020-07-08T22:41:07.135Z', 'updatedAt': '2020-07-08T22:42:19.327Z'}
source : {'sourceType': 'SITE_MEMBERS'}
id : long id string 2
emails : [{'tag': 'UNTAGGED', 'email': 'sampleemail2#yahoo.com'}]
phones : []
addresses : []
metadata : {'createdAt': '2020-07-03T00:51:21.127Z', 'updatedAt': '2020-07-04T03:26:16.370Z'}
source : {'sourceType': 'SITE_MEMBERS'}
Process finished with exit code 0
Each line is a string. I need each row of the csv to be a new contact (There are two sample contacts). The columns should be the keys. I plan to use the csv module to writerow(Fields), where fields is a list of string (keys) such as Fields = [id, emails, phones, addresses, metadata, source]
All I really need is the emails in a single column of a csv though. Is there a way to maybe just get the email for each contact?
A CSV file with one column is basically just a text file with one item per line, but you can use the csv module to do it if you really want, as shown below.
I commented-out the 'python-requests' stuff and used some sample input for testing.
test_data = {
"contacts": [
{
"id": "long id string 1",
"emails": [
{
"tag": "UNTAGGED",
"email": "sampleemail1#yahoo.com"
}
],
"phones": [],
"addresses": [
{
"tag": "UNTAGGED",
"countryCode": "US"
}
],
"metadata": {
"createdAt": "2020-07-08T22:41:07.135Z",
"updatedAt": "2020-07-08T22:42:19.327Z"
},
"source": {
"sourceType": "SITE_MEMBERS"
}
},
{
"id": "long id string 2",
"emails": [
{
"tag": "UNTAGGED",
"email": "sampleemail2#yahoo.com"
}
],
"phones": [],
"addresses": [],
"metadata": {
"createdAt": "2020-07-03T00:51:21.127Z",
"updatedAt": "2020-07-04T03:26:16.370Z"
},
"source": {
"sourceType": "SITE_MEMBERS"
}
}
]
}
import csv
import json
import requests
auth_key = "my auth key"
output_filename = 'whatever.csv'
#r = requests.get("https://www.wixapis.com/crm/v1/contacts", headers={"Authorization": auth_key})
#print(r.status_code)
#json_obj = r.json()
json_obj = test_data # FOR TESTING PURPOSES
contacts_list = json_obj["contacts"]
with open(output_filename, 'w', newline='') as outp:
writer = csv.writer(outp)
writer.writerow(['email']) # Write csv header.
for contact in contacts_list:
email = contact['emails'][0]['email'] # Get the first one.
writer.writerow([email])
print('email csv file written')
Contents of whatever.csv file afterwards:
email
sampleemail1#yahoo.com
sampleemail2#yahoo.com
Update:
As pointed by #martineau, I just saw you can array in few values, you need to cater it. You may make them string with [].join() in the for loop
you can write it to csv like this using csv package.
import csv, json, sys
auth_key = "my auth key"
r = requests.get("https://www.wixapis.com/crm/v1/contacts", headers={"Authorization": auth_key})
print(r.status_code)
dict = r.json()
contacts_list = dict["contacts"]
output = csv.writer(sys.stdout)
#insert header(keys)
output.writerow(data[0].keys())
for i in contacts_list:
output.writerow(i.values())
At the end you can print and verify output

Python: bitly request

I'm trying to do a basic Bitly shortening URL call. However, I cannot seem to either push the json correctly, or deal with the json response correctly... I omitted some obvious variables for brevity and obfuscated some real values for security purposes.
import requests
import json
bitly_header = {'Authorization':'Bearer
some_long_secret_character_string_here', 'Content-Type':'application/json'}
bitly_data = {
"long_url": ""+long_url+"",
"group_guid": ""+bitly_guid+""
}
short_link_resp =requests.post(bitly_endpoint,data=bitly_data,headers=bitly_header)
short_link_json = short_link_resp.json()
short_link = short_link_json["link"]
Errors is "Key error: 'link'
The json I get from Postman is:
{
"created_at": "1970-01-01T00:00:00+0000",
"id": "bit.ly/2MjdrrG",
"link": "bit.ly/2MjdrrG",
"custom_bitlinks": [],
"long_url": "google.com/",
"archived": false,
"tags": [],
"deeplinks": [],
"references": {
"group": "https://api-ssl.bitly.com/v4/groups/Bi7i8IbM1x9"
}
}
try replace data with json:
short_link_resp =requests.post(bitly_endpoint, json=bitly_data, headers=bitly_header)
see the doc ref.

Categories

Resources