Python: JSONDecodeError: Expecting property name enclosed in double quotes - python

Need some expert help on how to debug this and force a double quotes where missing, so that i can get a successful response. It is throwing error here df = pd.io.json.json_normalize(rt.json(), record_path='offers'). The josn looks fine i have staged into csv, so not sure where the issue is
my Code
import requests
import csv
import json
import pandas as pd
from pandas.io.json import json_normalize
url = "https://authentication.skiapi.com/access_token"
payload = {
"client_id": "00c7fcf******",
"client_secret": "7676cd5a********",
"grant_type": "client_credentials"
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
r = response.json()
access_token = r.get('access_token')
print(response.json()['access_token'])
uri = "https://private-anon-73f9ac5d87-slinksmerchantapi.apiary-mock.com/v4/publisher/12633/offers?country=US"
headers = {'Authorization': access_token,'Content-Type': "application/json"}
rt = requests.get(uri, headers=headers)
df = pd.io.json.json_normalize(rt.json(), record_path='offers') ###problem is here
#print(df)
df.to_csv(r"C:\\Users\ral\Downloads\\offers.csv", index=False)
My Sample JSON
{
"has_more": true
"offers": [{
"coupon_code": null
"terms": null
"description": "40% Off Comforters & Other Cool Bedding Stuff Online at BoxLunch! Stock up on select blankets and bedding online only for a limited time -- See site for details. Valid 3/3-3/5"
"offer_starts": "2017-03-03 08:00:00"
"title": "40% Off Comforters & Other Cool Bedding Stuff Online at BoxLunch!"
"url": "http://www.boxlunch.com/home/bedroom/?soffer=152034"
"merchant_details": {
"domain": "boxlunchgifts.com"
"verticals": []
"country_code": null
"id": 393756
"metadata": {}
"favourite": false
"partner_type": null
"merchant_id": 383288
"advertiser_id": 123456
"name": "BoxLunch"
"countries": []
"domains": [
"boxlunchgifts.com"
"boxlunch.com"
]
}
"offer_type": "sale"
"id": 152034
"offer_ends": "2017-03-05 08:00:00"
}]
"last_val": 152034
"next_val": 152032
"num_returned": 1
}

The JSON is not fine - as per comments commas are missing plus true should be True and null should be None in python
Additionally you are using deprecated interface to json_normalize
what does json.dumps(rt.json(), indent=2) return? Valid json?
patched json
json = {
"has_more": True,
"offers": [{
"coupon_code": None,
"terms": None,
"description": "40% Off Comforters & Other Cool Bedding Stuff Online at BoxLunch! Stock up on select blankets and bedding online only for a limited time -- See site for details. Valid 3/3-3/5",
"offer_starts": "2017-03-03 08:00:00",
"title": "40% Off Comforters & Other Cool Bedding Stuff Online at BoxLunch!",
"url": "http://www.boxlunch.com/home/bedroom/?soffer=152034",
"merchant_details": {
"domain": "boxlunchgifts.com",
"verticals": [],
"country_code": None,
"id": 393756,
"metadata": {},
"favourite": False,
"partner_type": None,
"merchant_id": 383288,
"advertiser_id": 123456,
"name": "BoxLunch",
"countries": [],
"domains": [
"boxlunchgifts.com",
"boxlunch.com"
]
},
"offer_type": "sale",
"id": 152034,
"offer_ends": "2017-03-05 08:00:00"
}],
"last_val": 152034,
"next_val": 152032,
"num_returned": 1
}
pd.json_normalize(json, record_path="offers")

Related

create Xero invoice using python request raise "No data has been processed for this endpoint. This endpoint is expecting Invoice data to be specifed"

I am trying to create an Invoice in Xero accounting using one of the Xero provided rest api, i used a Python requests library to access the certain Invoice rest api but unable to create an invoice. It raise following error
{'ErrorNumber': 17, 'Type': 'NoDataProcessedException', 'Message': 'No data has been processed for this endpoint. This endpoint is expecting Invoice data to be specifed in the request body.'}
Here is my my python code,
def XeroRequests():
new_tokens = XeroRefreshToken('*****************************')
xero_tenant_id = XeroTenants(new_tokens[0])
get_url = 'https://api.xero.com/api.xro/2.0/Invoices'
response = requests.post(get_url,
headers = {
'Authorization': 'Bearer ' + new_tokens[0],
'Xero-tenant-id': xero_tenant_id,
'Accept': 'application/json'
},
data = {
"Type": "ACCREC",
"Contact": {
"ContactID": "eaa28f49-6028-4b6e-bb12-d8f6278073fc"
},
"Date": "\/Date(1518685950940+0000)\/",
"DueDate": "\/Date(1518685950940+0000)\/",
"DateString": "2009-05-27T00:00:00",
"DueDateString": "2009-06-06T00:00:00",
"LineAmountTypes": "Exclusive",
"LineItems": [
{
"Description": "Consulting services as agreed (20% off standard rate)",
"Quantity": "10",
"UnitAmount": "100.00",
"AccountCode": "200",
"DiscountRate": "20"
}
]
})
json_response = response.json()
print("POST response ", json_response)
Whats wrong i did here?
You need to give data like this as per the API documentation
data = {
"Invoices": [{
"Type": "ACCREC",
"Contact": {
"ContactID": "eaa28f49-6028-4b6e-bb12-d8f6278073fc"
},
"Date": "\/Date(1518685950940+0000)\/",
"DueDate": "\/Date(1518685950940+0000)\/",
"DateString": "2009-05-27T00:00:00",
"DueDateString": "2009-06-06T00:00:00",
"LineAmountTypes": "Exclusive",
"LineItems": [
{
"Description": "Consulting services as agreed (20% off standard rate)",
"Quantity": "10",
"UnitAmount": "100.00",
"AccountCode": "200",
"DiscountRate": "20"
}
]
}
]
}

Netsuite Rest API returns "No Content" status (204) when completed successfully

i use the requests library. how can this be the default behavior? any way to return the ID of the item created?
def create_sales_order():
url = f"https://{url_account}.suitetalk.api.netsuite.com/services/rest/record/v1/salesOrder"
data = {
"entity": {
"id": "000"
},
"item": {
"items": [
{
"item": {
"id": 25
},
"quantity": 3,
"amount": 120
}
]
},
"memo": "give me money",
"Department": "109"
}
body = json.dumps(data)
response = client.post(url=url, headers=headers, data=body)
print(response.text)
Ok so it turns out that the header returned in the 204 empty response contains a link to the created item (Location is the key name in the json returned) , which is sufficient to do another get request and have all the info returned.

400 Bad Request POST request

I'm programing in Python some API application, using POSTMAN, and a Bearer token. I already receive the token, and to some GET with success response.
But when doing a insert of a record I got 400 Bad request error, this is the code I'm using for adding the record
def add_identity(token, accountid, newIdentity):
end_point = f"https://identityservice-demo.clearid.io/api/v2/accounts/{accountid}/identities/"
headers = CaseInsensitiveDict()
headers["Content-type"] = "application/json; charset=utf-8"
headers["Authorization"] = f"Bearer {token}"
response = requests.request("POST", end_point, data=newIdentity, headers=headers)
print(f"{response.reason} - {response.status_code}")
the variable newIdentity has the following data
nID = {
"privateData": {
"birthday": "1985-30-11T18:23:27.955Z",
"employeeNumber": "99999999",
"secondaryEmail": "",
"cityOfResidence": "Wakanda",
"stateOfResidence": "Florida",
"zipCode": "102837",
"phoneNumberPrimary": "(999)-999-999)",
"phoneNumberSecondary": "+5-(999)-999-9999"
},
"companyData": {
"approvers": [
{
"approverId": ""
}
],
"supervisorName": "Roger Rabbit",
"departmentName": "Presidency",
"jobTitle": "President",
"siteId": "string",
"companyName": "ACME Inc",
"workerTypeDescription": "",
"workerTypeCode": ""
},
"systemData": {
"hasExtendedTime": "true",
"activationDateUtc": "2022-03-16T18:23:27.955Z",
"expirationDateUtc": "2022-03-16T18:23:27.955Z",
"externalId": "999999",
"externalSyncTimeUtc": "2022-03-16T18:23:27.955Z",
"provisioningAttributes": [
{
"name": ""
}
],
"customFields": [
{
"customFieldType": "string",
"customFieldName": "SSNO",
"customFieldValue": "9999999"
}
]
},
"nationalIdentities": [
{
"nationalIdentityNumber": "0914356777",
"name": "Passport",
"issuer": "Wakanda"
}
],
"description": "1st Record ever",
"status": "Active",
"firstName": "Bruce",
"lastName": "Wayne",
"middleName": "Covid",
"displayName": "Bruce Wayne",
"countryCode": "WK",
"email": "bruce.wayne#wakanda.com",
"creationOnBehalf": "ACME"
}
what could solve the problem?
the swagger for the API is
https://identityservice-demo.clearid.io/swagger/index.html#/Identities/get_api_v2_accounts__accountId__identities
Thanks for your help in advance
data have to be a dict ,, you can try import json and data=json.dumps(newIdentity) ,
and if it keeps returning 400 , check well that all the parameters are accepted by the api by recreating the request with Postman or any request editor, and if the api uses any web interface check what is the reason for that 400 . This was translated by Google so I don't know if I said something nonsense :)

Video file is stuck at 0% when being uploaded via YouTube API V3 with Python (Resumable Uploads)

I'm uploading a resumable video on YouTube using YouTube API V3. When the code is executed, the status_code in response is 200 (but according to Official documentation, 201 is needed if the API works fine ).
When I open the YouTube channel, the video is there showing "0 % processing".
Moreover, after sometime there's a message "Processing abandoned" (as in the screenshot attached).
I have tried to include the parameters needed in the script, but nothing is working to change the processing level of video on YouTube channel.
The code here is as given below:
import requests
import json
import httplib2
import sys
class youtube:
#Access token obtained from OAuth 2.0 Playground
token = 'ya29.a0Af................................'
def resumable_uploads(self):
token = self.token
url = 'https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&part=snippet,status,contentDetails'
headers = {'Authorization': 'Bearer {}'.format(token), 'host': 'www.googleapis.com', 'content-type': 'application/json; charset=UTF-8', 'X-Upload-Content-Type': 'video/*'}
body = {
"snippet": {
"title": "Video 2 by Sidra ",
"description": "This is a description of my video",
"tags": ["cool", "video", "more keywords"],
"categoryId": 22
},
"status": {
"privacyStatus": "public",
"embeddable": True,
"license": "youtube",
"selfDeclaredMadeForKids" : True
}
}
response = requests.request('POST', url, headers=headers, data=json.dumps(body))
print("status_code: ", response.status_code)
if response.status_code == 200:
location = response.headers['location']
headers = {'Authorization': 'Bearer {}'.format(token),'content-type': 'video/*'}
#converting file into Bytes
video_file= open("testVideo.mp4", "rb")
file_content = video_file.read()
video_file.close()
body = {
"videoFile" : file_content
}
response = requests.request('PUT', location, headers=headers, data=body)
print(response.text)
print("status_code: ", response.status_code)
obj = youtube()
obj.resumable_uploads()
The response in console is as :
status_code: 200
{
"kind": "youtube#video",
"etag": "0rZIqeGvCifiyfQymb8CKXsC6CI",
"id": "YF2DQDACB4M",
"snippet": {
"publishedAt": "2020-08-28T17:29:12Z",
"channelId": "UCXonQaqsiqTV_YqYsB6W4Dg",
"title": "Video 2 by Sidra",
"description": "This is a description of my video",
"thumbnails": {
"default": {
"url": "https://i.ytimg.com/vi/YF2DQDACB4M/default.jpg",
"width": 120,
"height": 90
},
"medium": {
"url": "https://i.ytimg.com/vi/YF2DQDACB4M/mqdefault.jpg",
"width": 320,
"height": 180
},
"high": {
"url": "https://i.ytimg.com/vi/YF2DQDACB4M/hqdefault.jpg",
"width": 480,
"height": 360
}
},
"channelTitle": "Sidra Sial",
"tags": [
"cool",
"video",
"more keywords"
],
"categoryId": "22",
"liveBroadcastContent": "none",
"localized": {
"title": "Video 2 by Sidra",
"description": "This is a description of my video"
}
},
"contentDetails": {
"duration": "P0D",
"dimension": "2d",
"definition": "sd",
"caption": "false",
"licensedContent": false,
"contentRating": {},
"projection": "rectangular",
"hasCustomThumbnail": false
},
"status": {
"uploadStatus": "uploaded",
"privacyStatus": "public",
"license": "youtube",
"embeddable": true,
"publicStatsViewable": true,
"selfDeclaredMadeForKids": true
}
}
status_code: 200
The screenshot from YouTube Channel:
I personally would not recommend you to implement resumable video uploading using bare HTTP request methods. That's quite tricky to done it right.
It's more feasible to start from a fully working example, and modify it such that to fit your needs.
In any case, here is the official (quite heavy) documentation of the Resumable Upload Protocol.
Only having a first glance over your code, I noticed you missed passing to the first HTTP request method call -- POST -- the header X-Upload-Content-Length. (Note that I did not analyzed your code in its entirety; do follow my advise stated above.)

Python post request, problem with posting

I'm trying to write a typeform bot but I am a totally beginner so I have problems with request.post
I am trying to fill this typeform: https://typeformtutorial.typeform.com/to/aA7Vx9
by this code
import requests
token = requests.get("https://typeformtutorial.typeform.com/app/form/result/token/aA7Vx9/default")
data = {"42758279": "true",
"42758410": "text",
"token": token}
r = requests.post("https://typeformtutorial.typeform.com/app/form/submit/aA7Vx9", data)
print(r)
I think that something is wrong with "data" and I am not sure if I use token in a good way. Could you help me?
So, first of all, you need to get another field with the token. To do that, you should pass the header 'accept': 'application/json' in your first request. In the response, you'll get the json object with the token and landed_at parameters. You should use them in the next step.
Then, the post data shoud be different from what you're passing. See the network tab in the browser's developer tools to find out the actual template. It has a structure like that:
{
"signature": <YOUR_SIGNATURE>,
"form_id": "aA7Vx9",
"landed_at": <YOUR_LANDED_AT_TIME>,
"answers": [
{
"field": {
"id": "42758279",
"type": "yes_no"
},
"type": "boolean",
"boolean": True
},
{
"field": {
"id": "42758410",
"type": "short_text"
},
"type": "text",
"text": "1"
}
]
}
And finally, you should convert that json to text so the server would successfully parse it.
Working example:
import requests
import json
token = json.loads(requests.post(
"https://typeformtutorial.typeform.com/app/form/result/token/aA7Vx9/default",
headers={'accept': 'application/json'}
).text)
signature = token['token']
landed_at = int(token['landed_at'])
data = {
"signature": signature,
"form_id": "aA7Vx9",
"landed_at": landed_at,
"answers": [
{
"field": {
"id": "42758279",
"type": "yes_no"
},
"type": "boolean",
"boolean": True
},
{
"field": {
"id": "42758410",
"type": "short_text"
},
"type": "text",
"text": "1"
}
]
}
json_data = json.dumps(data)
r = requests.post("https://typeformtutorial.typeform.com/app/form/submit/aA7Vx9", data=json_data)
print(r.text)
Output:
{"message":"success"}

Categories

Resources