Python | Add 2 of The Same Keys In A Dict - python

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]

Related

Python dictionary formatting "if"

here is my code :
while True:
event = recieve_json_response(ws)
try:
if event['d']['guild_id'] == "699288260479942686" and event['d']['channel_id'] == "831878180586389514":
content = event['d']
print(f"{content}")
op_code = event('op')
if op_code == 11:
print('heartbeat received')
except:
pass
how can i add a var to this "if" part that prints the content var only if in event, a certain var contains a certain word
if event['d']['guild_id'] == "699288260479942686" and event['d']['channel_id'] == "831878180586389514":
here is the whole event dictionary :
d = {
"embeds": [
{
"type": "rich",
"timestamp": "2022-06-26T17:01:21.432000+00:00",
"footer": {"text": "© XkijuX & Co"},
"fields": [
{
"value": "+ `130` :gold:\n+ `65` :diamond:\n+ `55` :obsidian:\n\n:blank::blank::blank::blank::blank::blank::blank::blank:",
"name": "**During the session you found:**",
"inline": True,
},
{
"value": ":diamond: → `15370` durability left.",
"name": "**Your Pickaxe:**",
"inline": True,
},
],
"color": 32952,
"author": {
"proxy_icon_url": "https://images-ext-1.discordapp.net/external/c07-xyFM1v0DMWTunoCcOYoM-TQ02lkVONCAtmXLrko/https/cdn.discordapp.com/avatars/319534390461988866/44f0274292e7954e1ddc7d759d6f1e89.webp",
"name": "arsene#8880",
"icon_url": "https://cdn.discordapp.com/avatars/319534390461988866/44f0274292e7954e1ddc7d759d6f1e89.webp",
},
}
]
}
i want to make the code do like :
if this
event['d']['embeds'][0]['fields'][0]['name']
name var contains the word "session", event is printed
Use the in keyword.
For example:
if "session" in event['d']['embeds'][0]['fields'][0]['name']:
# do something

How to delete object in json

"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'

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

Remove Non-Updated Text/Object In JSON File With Python

This script updates the code in the json file with the users input but doesn't replace the placeholder text Screenshot URL X x is a number (1, 5). I want to remove the placeholder text that hasn't been updated by the script with the user input. It was working before but now it isn't and I can find out why. Any help will be welcomed! Thanks!
Code:
# 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
print("Press return/enter to enter another url or press it again with nothing entered to stop asking and continue the script.")
for number, screen_shot in enumerate(screen_shots):
new_url = input("Screnshot URL: ").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:
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)
JSON File:
{
"minVersion": "0.1",
"headerImage": "Header Image URL",
"tintColor": "",
"tabs": [
{
"tabname": "Details",
"views": [
{
"title": "Package Name",
"useBoldText": true,
"useBottomMargin": false,
"class": "DepictionSubheaderView"
},
{
"itemCornerRadius": 6,
"itemSize": "{160, 275.41333333333336}",
"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"
}
],
"class": "DepictionScreenshotsView"
},
{
"markdown": "This is a 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": "Version",
"text": "1.2",
"class": "DepictionTableTextView"
},
{
"title": "Released",
"text": "1/1/11",
"class": "DepictionTableTextView"
},
{
"title": "Price",
"text": "Free",
"class": "DepictionTableTextView"
},
{
"title": "Developer",
"text": "Dev",
"class": "DepictionTableTextView"
},
{
"title": "Contact Support",
"action": "",
"class": "DepictionTableButtonView"
},
{
"spacing": 16,
"class": "DepictionSpacerView"
},
{
"spacing": 20,
"class": "DepictionSpacerView"
}
],
"class": "DepictionStackView"
},
{
"tabname": "Changelog",
"views": [
{
"title": "1.2",
"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 1/1/11</small>",
"useRawFormat": true,
"class": "DepictionMarkdownView"
}
],
"class": "DepictionStackView"
}
],
"class": "DepictionTabView"
}
Does this work?
import json
file_name = "test.json"
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
print("Press return/enter to enter another url or press it again with nothing entered to stop asking and continue the script.")
for number, screen_shot in enumerate(screen_shots):
new_url = input("Screnshot URL: ").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:
break
# Remove all entries which we did not update
screen_shots = screen_shots[:number]
full_data['tabs'][0]['views'][1]['screenshots'] = screen_shots #-> this lines removes the placeholder text that is not updated by the user
# Save the data
with open(file_name, 'w') as fh:
json.dump(full_data, fh, indent=4)

Python/JSON KeyError

Please take a look at this post for more info I am trying to find something like this
screen_shots = full_data['tabs'][0]['views'][1]['screenshots']
but for a new JSON file but I keep getting
KeyError: 'screenshots'
I tried a few things to fix it but nothing works so any help will be welcomed
JSON
{
"minVersion":"0.1",
"class":"DepictionTabView",
"tintColor":"#2cb1be",
"headerImage":"",
"tabs":[ {
"tabname":"Details",
"class":"DepictionStackView",
"tintColor":"#2cb1be",
"views":[ {
"class": "DepictionSubheaderView", "useBoldText": true, "useBottomMargin": false, "title": "Description"
}
,
{
"class": "DepictionMarkdownView", "markdown": "<p>This is a description...<\/p>", "useRawFormat": true
}
,
{
"class": "DepictionSeparatorView"
}
,
{
"class": "DepictionSubheaderView", "useBoldText": true, "useBottomMargin": false, "title": "Screenshots"
}
,
{
"class":"DepictionScreenshotsView",
"itemCornerRadius":6,
"itemSize":"{160, 284.44444444444}",
"screenshots":[ {
"accessibilityText": "Screenshot", "url": "Screenshot URL 1"
}
]
}
,
{
"class": "DepictionSeparatorView"
}
,
{
"class": "DepictionSubheaderView", "useBoldText": true, "useBottomMargin": false, "title": "Information"
}
,
{
"class": "DepictionTableTextView", "title": "Author", "text": "User"
}
,
{
"class": "DepictionTableTextView", "title": "Version", "text": "1.0"
}
,
{
"class": "DepictionTableTextView", "title": "Price", "text": "free"
}
,
{
"class": "DepictionSpacerView", "spacing": 16
}
,
{
"class":"DepictionStackView",
"views":[
{
"class": "DepictionTableButtonView", "title": "Support", "action": "", "openExternal": true
}
]
}
,
{
"class": "DepictionSpacerView", "spacing": 16
}
]
}
,
{
"tabname":"Changelog",
"class":"DepictionStackView",
"tintColor":"#2cb1be",
"views":[
{
"class": "DepictionSubheaderView", "useBoldText": true, "useBottomMargin": false, "title": "1.0"
}
,
{
"class": "DepictionMarkdownView", "markdown": "<ul>\n<li>Initial release.<\/li>\n<\/ul>", "useRawFormat": true
}
]
}
]
}
In your JSON, many of the views do not have a screenshots key. The 2nd view (views[1]) definitely does not while the 5th view (views[4]) does.
If you're trying to collect all the screenshots from the views you'll need to use a loop and some conditional logic to find them.
screenshots = [] # an accumulator to collect our screenshots
for view in full_data['tabs'][0]['views']: # loop over each view
if 'screenshots' in view: # only process views with a screenshots key
# there can be multiple screenshots per view, so concatenate them to our accumulator
screenshots += view['screenshots']
You can further simplify this to a list comprehension
screenshots = [*screenshot for screenshot in full_data['tabs'][0]['views'] if 'screenshots' in view]
The *screenshot tells Python to "unroll" the list of screenshots. Adding each item to the list, rather then inserting a list into our list.
In the example you posted:
screen_shots = full_data['tabs'][0]['views'][1]['screenshots']
Goes to:
{
"class": "DepictionMarkdownView", "markdown": "<p>This is a description...<\/p>", "useRawFormat": true
}
Which doesn't have any key called screenshots. Your JSON keys at that level are not guaranteed to have that key. I'm guessing that screenshots will only be there if class is DepictionScreenshotsView.
So you can try:
tab = full_data['tabs'][0]
screen_shots = [tab['views'][i]['screenshots'] for i in range(len(tab)) if tab['view'][i]['class'] == 'DepictionScreenshotsView')

Categories