I am unable to find attribute values from JSON data in python - python

I want to find id and options in this JSON data.
Here's What I did so far.
data = """
"list": null,
"promotionID": "",
"isFreeShippingApplicable": true,
"html": "\n\n\n<div class=\"b-product-tile-price\">\n \n \n\n\n\n<span class=\"b-product-tile-price-outer\">\n <span class=\"b-product-tile-price-item\">\n 1200 €\n\n\n </span>\n</span>\n\n</div>\n\n"
},
"longDescription": "<ul>\n\t<li>STYLE: BQ4420-100</li>\n\t<li>Laufsohle: Gummi</li>\n\t<li>Obermaterial: beschichtetes Leder, Textil</li>\n\t<li>Innenmaterial: Textil</li>\n</ul>\n",
"shortDescription": null,
"availability": {
"messages": [
"Sofort lieferbar"
],
"inStockDate": null,
"custom": {
"code": null,
"label": null,
"orderable": true,
"sizeSelectable": true,
"badge": false
"""
find_values = json.loads(data)
id = find_values["id"]
variables = find_product_data["variables"]
print(id, variables)
The output is an erro but when I try to get the values of first the attribute action, it gets returned but not the others.

You can't access the id directly, because it is nested inside another dictionary. What you have to do is get that dict first and then access the id.
find_values = json.loads(data)
product = find_values["product"]
id_value = product("id")
If you are working with an IDE it could help to debug your code and see how the dict is actually nested.

Related

Python combine JSON arrays if value matches within objects irrespective of order

I wish to merge elements from a secondary JSON array into a primary array if values match.
Primary JSON:
primary = {
"#odata.context": "https://api.securitycenter.microsoft.com/api/$metadata#Collection(microsoft.windowsDefenderATP.api.PublicAssetVulnerabilityDto)",
"value": [
{
"id": "5afa3afc92a7c63d4b70129e0a6f33f63a427e21-_-CVE-2020-6494-_-microsoft-_-edge_chromium-based-_-81.0.416.77-_-",
"cveId": "CVE-2020-6494",
"machineId": "e5bc9d7e413ddd7902c2932e418702b84d0cc07",
"fixingKbId": null,
"productName": "edge_chromium-based",
"productVendor": "microsoft",
"productVersion": "81.0.416.77",
"severity": "Low"
},
{
"id": "7a704e17d1c2977c0e7b665fb18ae6e1fe7f3283-_-CVE-2016-3348-_-microsoft-_-windows_server_2012_r2-_-6.3.9600.19728-_-3185911",
"cveId": "CVE-2016-3348",
"machineId": "7a704e17d1c2977c0e7b665fb18ae6e1fe7f3283",
"fixingKbId": "3185911",
"productName": "windows_server_2012_r2",
"productVendor": "microsoft",
"productVersion": "6.3.9600.19728",
"severity": "Low"
}]}
Secondary JSON:
secondary = {
"#odata.context": "https://api.securitycenter.microsoft.com/api/$metadata#Machines",
"value": [
{
"id": "e5bc9d7e413ddd7902c2932e418702b84d0cc07",
"computerDnsName": "mymachine1.contoso.com",
"firstSeen": "2018-08-02T14:55:03.7791856Z",
"lastSeen": "2018-08-02T14:55:03.7791856Z",
"osPlatform": "Windows10" "Windows11",
"version": "1709",
"osProcessor": "x64",
"lastIpAddress": "172.17.230.209",
"lastExternalIpAddress": "167.220.196.71",
"osBuild": 18209,
"healthStatus": "Active",
"rbacGroupId": 140,
"rbacGroupName": "The-A-Team",
"riskScore": "Low",
"exposureLevel": "Medium",
"isAadJoined": true,
"aadDeviceId": "80fe8ff8-2624-418e-9591-41f0491218f9",
"machineTags": [ "test tag 1", "test tag 2" ]
}
]
}
I would like to merge based off these key values:
machineId (primary json)
id (secondary json)
Within my json, you can see that the 0th element in Primary JSON has the same "machineId" as the 0th element in the secondary JSON's "id". Therefore I would like to append the lastSeen key and value from the secondary JSON into the primary JSON as shown beneath:
Merged:
merged = {
"id": "5afa3afc92a7c63d4b70129e0a6f33f63a427e21-_-CVE-2020-6494-_-microsoft-_-edge_chromium-based-_-81.0.416.77-_-",
"cveId": "CVE-2020-6494",
"machineId": "e5bc9d7e413ddd7902c2932e418702b84d0cc07",
"fixingKbId": null,
"productName": "edge_chromium-based",
"productVendor": "microsoft",
"productVersion": "81.0.416.77",
"severity": "Low"
"lastSeen": "2018-08-02T14:55:03.7791856Z"
}
I was making use of this beneath solution to merge:
for element in a:
for lastSeen in s:
print(primary['machineId'])
print(secondary['id'])
if primary['machineId'] == secondary['id']:
element["lastSeen"] = secondary["lastSeen"]
print(element)
This wasn't working to well for me. I understand there may be a more optimized solution opposed to making use of embedded for loops that I'm not aware of.
If any clarify is required, please get in touch. Thanks.
Essentially in pseudo-code:
For each value in primary:
For each value in secondary:
If primary["id"] equals secondary["machineId"]
Append secondary["lastSeen"] to primary

Extracting list of objects from API request response

I'm using an API call to retrieve JSON data, the response to the get request is formatted like this:
data: JSON representation of resource requested
linked: an object containing additional entities
meta: miscellaneous information based on the endpoint.
When I do:
DictData = response.json()
json_formatted_str = json.dumps(DictData, indent = 2)
print(json_formatted_str)
I get all three sections (data, linked, meta):
{
"meta": {},
"linked": {}
"data": [
{
"date_on_hold": null,
"cc": [],
"labels": [
"Sales/Licensing"
],
"agent": 8,
"person": 210
}
]
And when I do:
DictData = response.json()
json_formatted_str = json.dumps(DictData['data'], indent = 2)
print(json_formatted_str)
I specifically get the data section:
[
{
"date_on_hold": null,
"cc": [],
"labels": [
"Sales/Licensing"
],
"agent": 8,
"person": 210
}
]
How would I go about specifically extracting the "person" tuple in the "data" section? In this example, I would want to print out '210'.
I believe I'm getting a list of objects, and I'm currently printing out the "data" object, but how would I print/extract the "person" variable in the "data" object?
Use
json_dict["data"][0]["person"]
Since DictData['data'] is a list of 1 element, to get value of a single person you can do:
DictData['data'][0]['person']
In case you need to iterate over the data list you can do:
for element in DictData['data']:
print(element['person'])

How to parse Smartsheet API 2.0 Python SDK error results?

I'm trying to get the update_rows method working
(the answers here haven't helped yet:
cannot update row using Smartsheet API
)
and would like to capture and parse the results
results = smartsheet.Sheets.update_rows(test_sheet_id, [row])
print(results)
gives me this:
{"requestResponse": null, "result": {"shouldRetry": false, "name":
"InvalidRowLocationError", "code": 1062, "recommendation": "Do not retry
without fixing the problem.", "message": "Invalid row location.",
"statusCode": 400}}
Note that a success looks like this (snipped most of it):
{"resultCode": 0, "message": "SUCCESS", "version": 21, "result":
[{"discussions": [], "createdAt": null, "above": null, "modifiedAt":
null, "columns": [], "toTop": null, "sheetId": null, "siblingId":
4800885606901636, "permalink": null, "id": 6067523002099588,
"accessLevel": null, "conditionalFormat": null, "attachments": [],
"cells": [{"columnType": null, "displayValue": null, "linksOutToCells":
null, "strict": true, "hyperlink": null, "formula": null, "format": null,
"conditionalFormat": null, "columnId": 7600931584927620, "linkInFromCell":
null, "value": null}, {"columnType": null, "displayValue": null, "
... snip ...
This looks like a dictionary, but the keys, items, values aren't recognized.
Next it looks like json - but nothing I've tried (I don't know much about json yet) has worked either.
If I could get the resultCode from a success, that would be a start.
Better would be the value from result, but that appears to be a dictionary for a fail and a list for successes.
I'm confused. Any help appreciated.
I'm using Python 3.5, Smartsheet API 2.0 Python SDK
Craig
I figured it out.
results = smartsheet.Sheets.update_rows(test_sheet_id, [row])
returns an result object from the models\error_result.py code of the SDK.
That object has two methods of interest and each property can be referenced like so:
print(results.result.code)
returns the code (1062 for example)
The two methods are to_dict and to_json which can be accessed and printed like so:
print(results.result.to_dict())
gives:
{'shouldRetry': False, 'name': 'InvalidRowLocationError', 'code': 1062,
'recommendation': 'Do not retry without fixing the problem.', 'message':
'Invalid row location.', 'statusCode': 400}
my_dict = results.result.to_dict()
for key, value in my_dict.items():
print(key, value)
gives:
shouldRetry False
name InvalidRowLocationError
code 1062
recommendation Do not retry without fixing the problem.
message Invalid row location.
statusCode 400
and the to_json code
print(results.result.to_json())
gives
{
"shouldRetry": false,
"name": "InvalidRowLocationError",
"code": 1062,
"recommendation": "Do not retry without fixing the problem.",
"message": "Invalid row location.",
"statusCode": 400
}
and:
my_json = results.result.to_json()
my_dict = json.loads(my_json)
for key, value in my_dict.items():
print(key, value)
gives:
shouldRetry False
name InvalidRowLocationError
code 1062
recommendation Do not retry without fixing the problem.
message Invalid row location.
statusCode 400

export json data to csv from mongodb

I am having the problem with missing field name in python script when exported data to csv from mongodb. type field name exists in first record, but it does not appear in the rest of records. how to write python script to give null value for type field if it does not exist.
the sample of Mongodb collection:
"stages": [
{
"interview": false,
"hmNotification": false,
"hmStage": false,
"type": "new",
"isEditable": false,
"order": 0,
"name": {
"en": "New"
},
"stageId": "51d1a2f4c0d9887b214f3694"
},
{
"interview": false,
"hmNotification": true,
"isEditable": true,
"order": 1,
"hmStage": true,
"name": {
"en": "Pre-Screen"
},
"stageId": "51f0078d7297363f62059699"
},
{
"interview": false,
"hmNotification": false,
"hmStage": false,
"isEditable": true,
"order": 2,
"name": {
"en": "Phone Screen"
},
"stageId": "51d1a326c0d9887721778eae"
}]
the sample of Python script:
import csv
cursor = db.workflows.find( {}, {'_id': 1, 'stages.interview': 1, 'stages.hmNotification': 1, 'stages.hmStage': 1, 'stages.type':1, 'stages.isEditable':1, 'stages.order':1,
'stages.name':1, 'stages.stageId':1 })
flattened_records = []
for stages_record in cursor:
stages_record_id = stages_record['_id']
for stage_record in stages_record['stages']:
flattened_record = {
'_id': stages_record_id,
'stages.interview': stage_record['interview'],
'stages.hmNotification': stage_record['hmNotification'],
'stages.hmStage': stage_record['hmStage'],
'stages.type': stage_record['type'],
'stages.isEditable': stage_record['isEditable'],
'stages.order': stage_record['order'],
'stages.name': stage_record['name'],
'stages.stageId': stage_record['stageId']}
flattened_records.append(flattened_record)
when run the python script, it shows keyerror:"type". please help me how to add the missing field name in the script.
When you're trying to fetch values that might not exist in a Python dictionary, you can use the .get() method of the dict class.
For instance, let's say you have a dictionary like this:
my_dict = {'a': 1,
'b': 2,
'c': 3}
You can use the get method to get one of the keys that exist:
>>> print(my_dict.get('a'))
1
But if you try to get a key that doesn't exist (such as does_not_exist), you will get None by default:
>>> print(my_dict.get("does_not_exist"))
None
As mentioned in the documentation, you can also provide a default value that will be returned when the key doesn't exist:
>>> print(my_dict.get("does_not_exist", "default_value"))
default_value
But this default value won't be used if the key does exist in the dictionary (if the key does exist, you'll get its value):
>>> print(my_dict.get("a", "default_value"))
1
Knowing that, when you build your flattened_record you can do:
'stages.hmStage': stage_record['hmStage'],
'stages.type': stage_record.get('type', ""),
'stages.isEditable': stage_record['isEditable'],
So if the stage_record dictionary doesn't contain a key type, get('type') will return an empty string.
You can also try with just:
'stages.hmStage': stage_record['hmStage'],
'stages.type': stage_record.get('type'),
'stages.isEditable': stage_record['isEditable'],
and then stage_record.get('type') will return None when that stage_record doesn't contain a type key.
Or you could make the default "UNKNOWN"
'stages.type': stage_record.get('type', "UNKNOWN"),

How to access a possibly existing element derived from a JSON data tree?

I have a rather complex data structure derived from JSON with json.load(<filehandle>), e.g.
{
"sensors": {
"measurements": [
[
null,
null,
null
],
[
{
"sensor": "Fields 341",
"remote": null,
"mark": "reliable",
"duration": 81.54296875
},
{
"sensor": "Fields 341",
"remote": null,
"mark": "reliable",
"duration": 61.54534875
},
{
"sensor": "Fields 341",
"remote": null,
"mark": "reliable",
"duration": 61.89378945
}
]
]
}
}
The result are nested dictionaries and lists, e.g.
{u'sensors': {u'measurements': [[None, None, None],
[{u'duration': 81.54296875,
u'mark': u'reliable',
u'remote': None,
u'sensor': u'Fields 341'},
{u'duration': 61.545348750000002,
u'mark': u'reliable',
u'remote': None,
u'sensor': u'Fields 341'},
{u'duration': 61.89378945,
u'mark': u'reliable',
u'remote': None,
u'sensor': u'Fields 341'}]]}}
The goal is to take the data and stuff it in a database via sqlalchemy. Like this:
for item in sensors["measurements"]:
for j in range(len(sensors["measurements"])):
DBTable.DBField = item[j]["sensor"]
...
The problem with this is: Any parts in the data could be replaced with null/None in case the measurements where erroneous (like the first one). If so the DBFields should be assigned None. If this is the case the assignment raises an exception:
TypeError: 'NoneType' object is unsubscriptable
Is there a sane way to get the for loop to run without raising the exception (maybe using .get() of somekind)? If not, what is the best way to handle this non-existent data structures?
You can preconstruct a dictionary with defaults that you like:
defaults = {"sensor": None, "remote": None", "mark": None, "duration": None }
Then you can do:
DBTable.DBField = item.get(j, defaults)["sensor"]
You could also use a collections.defaultdict for the defaults item, which will allow you to provide a default for any key accessed.
May be this would work
for item in sensors["measurements"]:
for j in range(len(sensors["measurements"])):
try:
DBTable.DBField = item[j]["sensor"]
except:
DBTable.DBField = None

Categories

Resources