How to delete object in json - python

"Admins": [
{
"Admin_name": "admin",
"Admin_pass": "admin"
},
{
"Admin_name": "administrator",
"Admin_pass": "password"
}
],
"Teachers": [
{
"Name": "Yersin Zhanabekov",
"Course": "Physical Culture",
"Login": "Yersin.Zhanabekov",
"Pass": "Yersin123",
"Mark": null
},
{
"Name": "Kayrat Mynbayev",
"Course": "Theory of Probability and Mathematical Statistics",
"Login": "Kayrat.Mynbayev",
"Pass": "Kayrat123",
"Mark": null
},
{
"Name": "Magzhan Ikram",
"Course": "Python",
"Login": "Magzhan .Ikram",
"Pass": "Magzhan123",
"Mark": null
},
{
"Name": "Mag",
"Course": "Python",
"Login": "Magzhan .Ikram",
"Pass": "Magzhan123",
"Mark": null
}
], },
{
"Name": "Mag",
"Course": "Python",
"Login": "Magzhan",
"Pass": "Magzhan123",
"Mark": null
}
],
with open('dict.json', 'r') as rf:
dataRead = json.load(rf)
log = input("Your username: ")
pas = input("Your password: ")
for name in dataRead['Admins']:
if log == name['Admin_name'] and pas == name['Admin_pass']:
y = {'Name': "Hello"}
dataRead['Teachers'][3]['Name'].pop()
dataRead['Teachers'][3]['Name'].append(y)
with open('dict.json', 'w') as rf:
dataRead = json.dump(dataRead,rf)
I want to delete the object Name, and change it to a new one.With pop() or .delete().
But anyway, I get the same error.
What should I do?
Error is:
Traceback (most recent call last):
dataRead ['Teachers'] [3] ['Name']. pop () AttributeError: 'str' object has no attribute 'pop'

You should just do
dataRead['Teachers'][3]['Name'] = "Hello"

dataRead['Teachers'] is a list. Once you've identified the index of the item in that list that you want to remove (e.g., 3) then dataRead(['Teachers'].pop(3)

You can also look into JSONPath expressions (using libraries like jsonpath-ng). It gives you greater flexibility to navigate through JSON objects. Here are some examples:
changing Name for specific element:
from jsonpath_ng.ext import parser
for match in parser.parse("$.Teachers[?(#.Name=='Mag')]").find(x):
match.value['Name'] = 'New'
Popping Name from elements with Name attribute:
for match in parser.parse("$.Teachers[?(#.Name)].[*]").find(x):
match.value.pop('Name')
Setting Name for all nodes in Teachers
for match in parser.parse("$.Teachers.[*]").find(x):
match.value['Name'] = 'New name'

Related

How to print a specific item from within a JSON file into python

I want to print a user from a JSON list into Python that I select however I can only print all the users. How do you print a specific user? At the moment I have this which prints all the users out in a ugly format
import json
with open('Admin_sample.json') as f:
admin_json = json.load(f)
print(admin_json['staff'])
The JSON file looks like this
{
"staff": [
{
"id": "DA7153",
"name": [
"Fran\u00c3\u00a7ois",
"Ullman"
],
"department": {
"name": "Admin"
},
"server_admin": "true"
},
{
"id": "DA7356",
"name": [
"Bob",
"Johnson"
],
"department": {
"name": "Admin"
},
"server_admin": "false"
},
],
"assets": [
{
"asset_name": "ENGAGED SLOTH",
"asset_type": "File",
"owner": "DA8333",
"details": {
"security": {
"cia": [
"HIGH",
"INTERMEDIATE",
"LOW"
],
"data_categories": {
"Personal": "true",
"Personal Sensitive": "true",
"Customer Sensitive": "true"
}
},
"retention": 2
},
"file_type": "Document",
"server": {
"server_name": "ISOLATED UGUISU",
"ip": [
10,
234,
148,
52
]
}
},
{
"asset_name": "ISOLATED VIPER",
"asset_type": "File",
"owner": "DA8262",
"details": {
"security": {
"cia": [
"LOW",
"HIGH",
"LOW"
],
"data_categories": {
"Personal": "false",
"Personal Sensitive": "false",
"Customer Sensitive": "true"
}
},
"retention": 2
},
},
]
I just can't work it out. Any help would be appreciated.
Thanks.
You need to index into the staff list, e.g.:
print(admin_json['staff'][0])
I suggest reading up a bit on dictionaries in Python. Dictionary values can be set to any object: in this case, the value of the staff key is set to a list of dicts. Here's an example that will loop through all the staff members and print their names:
staff_list = admin_json['staff']
for person in staff_list:
name_parts = person['name']
full_name = ' '.join(name_parts) # combine name parts into a string
print(full_name)
Try something like this:
import json
def findStaffWithId(allStaff, id):
for staff in allStaff:
if staff["id"] == id:
return staff
return {} # no staff found
with open('Admin_sample.json') as f:
admin_json = json.load(f)
print(findStaffWithId(admin_json['staff'], "DA7356"))
You can list all the users name with
users = [user["name"] for user in admin_json['staff']]
You have two lists in this JSON file. When you try to parse it, you'll be reach a list. For example getting the first staff id:
print(admin_json['staff'][0]['id'])
This will print:
DA7153
When you use "json.loads" this will simply converts JSON file to the Python dictionary. For further info:
https://docs.python.org/3/tutorial/datastructures.html#dictionaries

Error when trying to access data via API using Python

I get error when trying to access details about servers storage using API. I want to extract backup status which is state in json:
{
"storage": {
"access": "private",
"backup_rule": {},
"backups": {
"backup": []
},
"license": 0,
"part_of_plan": "",
"servers": {
"server": [
""
]
},
"size": ,
"state": "online",
"tier": "",
"title": "",
"type": "",
"uuid": "",
"zone": ""
}
}
When I execute this code:
bkpdet = requests.get('https://fffff.com/1.2/storage/08475', auth=HTTPBasicAuth('login', 'pass'))
bkpdet_json = bkpdet.json()
datastg = bkpdet.json()
print(datastg)
for sts in datastg['storage']:
bkpsts = sts['state']
print(bkpsts)
I get this error:
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
TypeError: string indices must be integers
How can I access state*?
The whole idea is to at the end get info about status using this code:
if bkpsts == "online":
print('Backup has been created.')
else bkpsts == "backuping":
print('Backup creation is in progress.')
else:
print(bkpdet.status_code)
I was searching but still cannot find what is wrong here.
When you use:
for sts in datastg['storage']:
sts will be a string key. You are trying to treat it like an dictionary.
If you just need the state value, you can access it directly:
datastg['storage']['state']
If you want to iterate all key value pairs under storage, you can use items() to both key and value.
for key, value in datastg['storage'].items():
print(key,":", value)
As #MarkMeyer advised I changed code like this:
bkpdet = requests.get('https://fffff.com/1.2/storage/08475', auth=HTTPBasicAuth('login', 'pass'))
bkpdet_json = bkpdet.json()
datastg = bkpdet.json()
bkpsts = datastg['storage']['state']
print(bkpsts)
It works perfectly!
The code below works
data = {
"storage": {
"access": "private",
"backup_rule": {},
"backups": {
"backup": []
},
"license": 0,
"part_of_plan": "",
"servers": {
"server": [
""
]
},
"size": 1,
"state": "online",
"tier": "",
"title": "",
"type": "",
"uuid": "",
"zone": ""
}
}
state = data['storage']['state']
print(state)
output
online

How to extract data using API and Python?

I have a banch of servers and I use API to extract data about storage.
To get details about storage uuid (named storage in json) I use code as below:
srvdet = requests.get('https://hhh.com/1.2/server/76856585', auth=HTTPBasicAuth('login', 'pass'))
srvdet_json = srvdet.json()
datas = srvdet.json()
print(datas)
And result in json:
{
"server": {
"boot_order": "",
"core_number": "2",
"created": ,
"firewall": "off",
"host": ,
"hostname": "hello",
"ip_addresses": {
"ip_address": [
{
"access": "private",
"address": "",
"family": ""
},
{
"access": "",
"address": "",
"family": "",
"part_of_plan": ""
}
]
},
"license": 0,
"memory_amount": "",
"nic_model": "",
"plan": "",
"plan_ipv4_bytes": "",
"plan_ipv6_bytes": "0",
"state": "started",
"storage_devices": {
"storage_device": [
{
"address": "",
"boot_disk": "0",
"part_of_plan": "",
"storage": "09845",
"storage_size": ,
"storage_title": "",
"type": ""
}
For now it works perfectly fine. The problem is when I need to get "09845" which is value for storage. When I try to use this code:
for storage in datas['server']['storage_devices']['storage_device']:
srvstorage = storage
print(srvstorage)
The result is:
{'storage': '09845', 'storage_size':, 'address': '', 'boot_disk': '0', 'type': '', 'part_of_plan': 'yes', 'storage_title': ''}
What am I doing wrong? How to save "09845" in variable?
EDIT:
Now I get error when trying to access details about storage.
I want to extract backup status which is state in json:
{
"storage": {
"access": "private",
"backup_rule": {},
"backups": {
"backup": []
},
"license": 0,
"part_of_plan": "",
"servers": {
"server": [
""
]
},
"size": ,
"state": "online",
"tier": "",
"title": "",
"type": "",
"uuid": "",
"zone": ""
}
}
When I execute this code:
bkpdet = requests.get('https://fffff.com/1.2/storage/08475', auth=HTTPBasicAuth('login', 'pass'))
bkpdet_json = bkpdet.json()
datastg = bkpdet.json()
print(datastg)
for sts in datastg['storage']:
bkpsts = sts['state']
print(bkpsts)
I get this error:
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
TypeError: string indices must be integers
The whole idea is to at the end get info about status using this code:
if bkpsts == "online":
print('Backup has been created.')
else bkpsts == "backuping":
print('Backup creation is in progress.')
else:
print(bkpdet.status_code)
I was searching but still can't find what is wrong here.
You miss a key when you want to access storage, you loop over it and it's fine. But in each iteration you get a dictionary from which you need to call the right key, in your case storage.
for storage in datas['server']['storage_devices']['storage_device']:
srvstorage = storage.get("storage", None)
print(srvstorage)
Note
get method will be preferable to use as you may encounter a device with out storage information inside, by using get you can avoid the KeyError.
You can just do
for device in datas['server']['storage_devices']['storage_device']:
device_storage = device['storage']
print(device_storage)

Python | Add 2 of The Same Keys In A Dict

How would I go about adding 2 of the same keys just with screenshoturl2 and screenshoturl1 from a dict to a JSON file?
This is the code I have right now and it works but it just only adds the first screenshoturl1 and not screenshoturl2 and I have no idea on how to make it add it. See replies here for more and maybe helpful info about my topic
#!/usr/bin/env python3
import os
import sys
import json
import fileinput
def NumberofScreenshots():
global numberofscreenshots
while True:
try:
numberofscreenshots = input("Number of Screenshots?: ")
if numberofscreenshots == '':
print("Please enter how much screenshots to include.")
continue
elif numberofscreenshots.isalpha():
print("Please enter a number not a string.")
continue
else:
break
except ValueError:
break
def ScreenshotURL():
global screenshoturl1, screenshoturl2
if numberofscreenshots == "1":
screenshoturl1 = input("Screenshot URL: ")
elif numberofscreenshots == "2":
screenshoturl1 = input("Screenshot URL: ")
screenshoturl2 = input("Screenshot URL: ")
else:
pass
def NumberofScreenshots1():
if numberofscreenshots == "1":
with open('path/to/json/file','r') as f:
data = json.loads(f.read())
data['tabs'][0]['views'][1]['screenshots'][0]
data['tabs'][0]['views'][1]['screenshots'] = data['tabs'][0]['views'][1]['screenshots'][0]
data['tabs'][0]['views'][1]['screenshots'] = {"accessibilityText": "Screenshot","url": screenshoturl1,"fullSizeURL": screenshoturl1}
with open('path/to/json/file', 'w') as f:
f.write(json.dumps(data))
else:
print("Try again.")
def NumberofScreenshots2():
global data
if numberofscreenshots == "2":
with open('path/to/json/file','r') as f:
data = json.loads(f.read())
data['tabs'][0]['views'][1]['screenshots'][0]
print(data)
data['tabs'][0]['views'][1]['screenshots'] = data['tabs'][0]['views'][1]['screenshots'][0]
print(data)
data['tabs'][0]['views'][1]['screenshots'].update({"accessibilityText": "Screenshot","url": screenshoturl1,"fullSizeURL": screenshoturl1, "accessibilityText": "Screenshot","url": screenshoturl2,"fullSizeURL": screenshoturl2})
print(data)
with open('path/to/json/file', 'w') as f:
f.write(json.dumps(data))
else:
print("Try again.")
print("Pick Template:")
print("1. Default")
template = input("Template Name/Number: ")
if (template == "1"):
NumberofScreenshots()
ScreenshotURL()
NumberofScreenshots1()
NumberofScreenshots2()
# Show the user a error if they enter a number for a template that can't be found.
else:
print("The template you are looking for can not be found!")
We are looking at the function called NumberofScreenshots2
JSON File:
{
"tabs": [
{
"tabname": "Details",
"views": [
{
"title": "Some Name",
"useBoldText": true,
"useBottomMargin": false,
"class": "DepictionSubheaderView"
},
{
"itemCornerRadius": 6,
"itemSize": "",
"screenshots": [
{
"accessibilityText": "Screenshot",
"url": "Screenshot URL 1",
"fullSizeURL": "Screenshot URL 1"
},
{
"accessibilityText": "Screenshot",
"url": "Screenshot URL 2",
"fullSizeURL": "Screenshot URL 2"
},
{
"accessibilityText": "Screenshot",
"url": "Screenshot URL 3",
"fullSizeURL": "Screenshot URL 3"
},
{
"accessibilityText": "Screenshot",
"url": "Screenshot URL 4",
"fullSizeURL": "Screenshot URL 4"
},
{
"accessibilityText": "Screenshot",
"url": "Screenshot URL 5",
"fullSizeURL": "Screenshot URL 5"
}
],
"ipad": {
"itemCornerRadius": 9,
"itemSize": "{320, 550.8266666666667}",
"screenshots": [
{
"accessibilityText": "Screenshot",
"url": " Screenshot URL?size=640",
"fullSizeURL": "Screenshot URL"
}
],
"class": "DepictionScreenshotView"
},
"class": "DepictionScreenshotsView"
},
{
"markdown": " Description",
"useSpacing": true,
"class": "DepictionMarkdownView"
},
{
"class": "DepictionSeparatorView"
},
{
"title": "Known Issues",
"class": "DepictionHeaderView"
},
{
"markdown": "None",
"useSpacing": true,
"class": "DepictionMarkdownView"
},
{
"class": "DepictionSeparatorView"
},
{
"title": "Latest Version",
"class": "DepictionHeaderView"
},
{
"title": "1.0",
"text": "Latest Version Number",
"class": "DepictionTableTextView"
},
{
"title": "Released",
"text": "3/10/19",
"class": "DepictionTableTextView"
},
{
"title": "Price",
"text": "Free",
"class": "DepictionTableTextView"
},
{
"title": "Developer",
"text": "TestDev",
"class": "DepictionTableTextView"
},
{
"title": "Contact Support",
"action": "",
"class": "DepictionTableButtonView"
},
{
"spacing": 16,
"class": "DepictionSpacerView"
},
{
"spacing": 20,
"class": "DepictionSpacerView"
}
],
"class": "DepictionStackView"
},
{
"tabname": "Changelog",
"views": [
{
"title": "1.0",
"useBoldText": true,
"useBottomMargin": true,
"class": "DepictionSubheaderView"
},
{
"markdown": "\t\n\u2022 Initial Release",
"useSpacing": false,
"class": "DepictionMarkdownView"
},
{
"markdown": "<small style=\"color: #999; margin-top: -8px;\">Released 3/10/2019</small>",
"useRawFormat": true,
"class": "DepictionMarkdownView"
}
],
"class": "DepictionStackView"
}
],
"class": "DepictionTabView"
}
I want it to remove everything in screenshots and re-add it with the user input that they enter in the screenshoturl1 and screenshoturl2 so it will delete everything like the placeholders in screenshots and only add 2 back with the url the user enters in screenshoturl1 and screenshoturl2 and help will be nice.
Thanks!
If I understand what you are trying to do here, it looks like you would like to update one or two of the URLs, one at a time.
What you could do is go over each screenshot item, one at a time, and either update it or stop. This is easier and also lets you update all of them if you want to. This also means we don't have to ask how many to do up front (we just stop when we don't get any more).
import json
# Load the data
file_name = 'path/to/json/file'
with open(file_name) as fh:
full_data = json.load(fh)
# Dig into the data to find the screenshots
screen_shots = full_data['tabs'][0]['views'][1]['screenshots']
# Loop over each screen shot, updating each one
for number, screen_shot in enumerate(screen_shots):
print("Screenshot", number)
print('\tCurrent data:', screen_shot)
new_url = input(
"\tPlease enter new URL (leave empty and press return to stop): "
).strip()
if new_url:
# Updating the data here will also update the 'full_data' object
# as we are just referencing a part of it, not making copies
screen_shot.update({"url": new_url, "fullSizeURL": new_url})
else:
print("\tAll done!")
break
# Remove all entries which we did not update
screen_shots = screen_shots[:number]
# Save the data
with open(file_name, 'w') as fh:
json.dump(full_data, fh, indent=4)
Something else you may want to look into is returning results from your functions instead of using global variables, as this can quickly get very confusing with bigger scripts.
You can have your value a collection (like a list or a tuple). For added convenience you can use defaultdict. So if you wanted to have two values for a key:
from collections import defaultdict
multiValueDict = defaultdict(list)
multiValueDict[1].append(1)
multiValueDict[1].append(2)
print(multiValueDict[1])
And this outputs:
[1, 2]

Need help pulling values from JSON using python, getting TypeError

Here's an example of the JSON I'm pulling from a URL:
[
{
"externalModelId": "500A000000RQOwnIAH",
"resource": {
"account": {
"externalModelId": "001A000001EucpoIAB",
"resource": {
"accountName": "Foobar",
"accountNumber": 1234567,
},
"resourceReliability": "Fresh"
},
"caseNumber": 1234567,
"created": "2015-06-12T19:06:22.000Z",
"createdBy": {
"externalModelId": "005A0000005mhdXIAQ",
"resourceReliability": "Fresh"
},
"description": "Example description",
"hoursInCurrentStatus": 406,
"internalPriority": "3 (Normal)",
"lastModified": "2015-06-22T14:08:18.000Z",
"owner": {
"externalModelId": "005A0000001sKDzIAM",
"resourceReliability": "Fresh"
},
"product": {
"resource": {
"line": {
"externalModelId": 21118,
"resource": {
"name": null
},
"resourceReliability": "Fresh"
},
"version": {
"externalModelId": 21988,
"resource": {
"name": "1.2"
},
"resourceReliability": "Fresh"
}
},
"resourceReliability": "Fresh"
},
"resourceCount": 0,
"sbrs": [
"Value"
],
"sbt": 139,
"severity": "4 (Low)",
"status": "Status Example",
"subject": "Subject Example",
"tags": [
"br",
"fs"
],
"targetDate": "2015-07-15T17:46:48.000Z",
"type": "Feature"
},
"resourceReliability": "Fresh"
},
I'm interested in pulling the following values from it:
caseNumber
subject
severity
sbt
sbrs
status
The code I currently have is:
#!/usr/bin/env python
import sys
import requests
import json
import os
# Setup
username = "XXX"
password = "XXX"
accountid = "12345"
# Formulate the string and then capture the output
url = "http://XXX{0}XXX{1}XXXXX".format(accountid, filedtime)
r = requests.get(url, auth=(username, password))
parsed = json.loads(r.text)
parent = parsed['resource']
# Using json_string for testing
#json_string = json.dumps(parsed, indent=4, sort_keys=True)
#print json_string
for item in parent:
print item['caseNumber']
print item['subject']
print item['severity']
print item['sbt']
print item['sbrs']
print item['status']
The code outputs a TypeError:
Traceback (most recent call last):
File "./newcase-notify.py", line 31, in <module>
parent = parsed['resource']
TypeError: list indices must be integers, not str
I've tried specifying something like:
parent = parsed['resource'][0]['type']
but that doesn't work. I think I'm confused at this point. If I don't specify a parent and simply iterate through 'parsed' like:
for item in parsed:
print item['caseNumber']
print item['subject']
print item['severity']
print item['sbt']
print item['sbrs']
print item['status']
I get KeyError's again.
My Question:
Given the information provided, how can I pull the above mentioned values from my JSON object?
I solved this by removing:
parent = parsed['resource']
and using:
for item in parsed:
print item['resource']['caseNumber']
print item['resource']['subject']
print item['resource']['severity']
etc.
If you look at the top of your JSON you'll notice this:
[
{
That means an array, with an object inside. You need to dereference that object form the array first. Hence why you're getting that jazz about list indices must be of type integer and not string. Once you do that it should work.
parent = parsed[0]['resource'] should fix you right up.
Just to help guide you with translating between the nomenclatures:
Array:JS as List:Python and Object:JS as Dict:Python.

Categories