Test values inside JSON using Python - python

I have this JSON in a file:
{"groupcolor":[
{"user":"group01", "color":"blue"},
{"user":"group02", "color":"yellow"},
{"user":"group03", "color":"green"}
]}
and I want to use Python(3) to verify if the content of "user" matches with "color". I've tried:
import json
with open('groupcolor.json') as f:
for line in f:
if f.user == group01 and f.color = blue:
print("ok!")
else:
print ("not ok")
but it obviously isn't the right syntax. most of the information that I found is focused on parsing or adding information, but I haven't found anything about checking the relation between two elements. is a way to do it in Python?

You definitely have the right idea: just the wrong syntax, as you point out.
As a comment suggests, you need to use json.load() (but not json.loads(), as json.loads() is for a string, not a file). This will rope in the json file as a dictionary.
import json
with open('groupcolor.json') as f:
json_dict = json.load(f)
users = json_dict["groupcolor"]
for item in users:
if item["user"] == "group01" and item["color"] == "blue":
print("ok!")
else:
print ("not ok")

Here is one solution:
import json
with open('groupcolor.json') as f:
group_color = json.load(f) # parse json into dict
group_color = group_color["groupcolor"] # get array out of dict
# create a dictionary where user is group01 and color is blue
search_criteria = dict(zip(("user", "color"), ("group01", "blue")))
for user_data in group_color:
message = "ok!" if user_data == search_criteria else "not ok"
print(message)

Related

Adding nested dictionaries into an already existing JSON file with dictionary

I've recently started to learn some python.
After finishing all the learnpython.org tutorials I'm trying something on my own (So you know my knowledge level).
I want to build a small script that lets you build a DnD character and save it in a file. The idea was to use JSON (Since this was included in the learnpython tutorials) and put in dictionaries along the lines of:
data = { playerName ; {"Character Name" : characterName, "Character Class" : characterClass...ect.}}
I was hoping that it is possible to add new dics into the JSON file inside that original data dic, So the dictionary is a list of playerName's that have the character dics under them.
Not only did I fail to get it exactly like this, I also fail at just adding following dictionaries without making the file unreadable. Here is my code, since it isn't very long:
import json
def dataCollection():
print("Please write your character name:")
characterName = input()
print("%s, a good name! \nNow tell me your race:" % characterName)
characterRace = input()
print("And what about the class?")
characterClass = input()
print("Ok so we have; \nName = %s \nRace = %s \nClass = %s \nPlease tell me the player name now:" % (characterName, characterRace, characterClass))
playerName = input()
print("Nice to meet you %s. \nI will now save your choices..." % playerName)
localData = { playerName :
{"Character Name" : characterName,
"Character Class" : characterClass,
"Character Race" : characterRace}}
with open("%s_data_file.json" % playerName, "a") as write_file:
json.dump(localData, write_file)
dataCollection()
with open("data_file.json", "r") as read_file:
data = json.load(read_file)
# different .json name here since I'm trying around with different files
print(data)
Edit: It might also be possible that JSON is not the "right" thing to use for my idea. If you have any alternative ideas for storing that information (Besides straight txt file), feel free to suggest them!
i made little modification, i try to read the file for init the data json, if it fail i init the data.
import json
def createPlayer():
print("Please write your character name : ")
characterName = input()
print("%s, a good name! \nNow tell me your race : " % characterName)
characterRace = input()
print("Nice to meet you %s. \nI will now save your choices..." % characterName)
try :
with open('data_file.json') as json_file:
data = json.load(json_file)
except :
data = {}
data['player'] = []
data['player'].append({
'name': characterName,
'race': characterRace,
})
with open("data_file.json", "w+") as write_file:
json.dump(data, write_file)
createPlayer()
with open("data_file.json", "r") as read_file:
data = json.load(read_file)
print(data)
I think that the way you think of a dictionnary might not be exactly what it is.
A dictionary is a data structure that can holds many key-value pairs.
Here the key to your dictionary would be the player's name and the value would be the dictionary that holds the character's name, class and race.
So a json file that holds a dictionary cannot be appended to because a json file can only hold 1 json object.
{ 'playerName': {...character\'s attributes...}}
If you were to open the file and append a json object (like you do at the end of dataCollection) then your file would be like this
{ 'playerName':
{...characters attributes...}
}
{ 'playerName2':
{...characters attributes...}
}
And when reading the file json will stop when the first json object it finds will end. So it won't load the 2nd dictionary.
If you want to add something to the dictionary inside your json file, you need to load the json file to access the dictionary and then add your new key-value pair and then dump this new dictionary. Which will result in the following json file:
{ 'playerName':
{...characters attributes...},
'playerName2':
{...characters attributes...}
}
I hope it's kinda clear.

Verify data on a file

I'm trying to make my life easier on my work, and writing down errors and solutions for that same errors. The program itself works fine when it's about adding new errors, but then I added a function to verify if the error exists in the file and then do something to it (not added yet).
The function doesn't work and I don't know why. I tried to debug it, but still not able to find the error, maybe a conceptual error?
Anyway, here's my entire code.
import sys
import os
err = {}
PATH = 'C:/users/userdefault/desktop/errordb.txt'
#def open_file(): #Not yet used
#file_read = open(PATH, 'r')
#return file_read
def verify_error(error_number, loglist): #Verify if error exists in file
for error in loglist:
if error_number in loglist:
return True
def dict_error(error_number, solution): #Puts input errors in dict
err = {error_number: solution}
return err
def verify_file(): #Verify if file exists. Return True if it does
archive = os.path.isfile(PATH)
return archive
def new_error():
file = open(PATH, 'r') #Opens file in read mode
loglist = file.readlines()
file.close()
found = False
error_number = input("Error number: ")
if verify_error(error_number, loglist) == True:
found = True
# Add new solution, or another solution.
pass
solution = str(input("Solution: "))
file = open(PATH, 'a')
error = dict_error(error_number, solution)
#Writes dict on file
file.write(str(error))
file.write("\n")
file.close()
def main():
verify = verify_file() #Verify if file exists
if verify == True:
new = str.lower(input("New job Y/N: "))
if new == 'n':
sys.exit()
while new == 'y':
new_error()
new = str.lower(input("New job Y/N: "))
else:
sys.exit()
else:
file = open(PATH, "x")
file.close()
main()
main()
To clarify, the program executes fine, it don't return an error code. It just won't execute the way I'm intended, I mean, it supposed to verify if certain error number already exists.
Thanks in advance :)
The issue I believe you're having is the fact that you're not actually creating a dictionary object in the file and modifying it but instead creating additional dictionaries every time an error is added then reading them back as a list of strings by using the .readlines() method.
An easier way of doing it would be to create a dictionary if one doesn't exist and append errors to it. I've made a few modifications to your code which should help.
import sys
import os
import json # Import in json and use is as the format to store out data in
err = {}
PATH = 'C:/users/userdefault/desktop/errordb.txt'
# You can achieve this by using a context manager
#def open_file(): #Not yet used
#file_read = open(PATH, 'r')
#return file_read
def verify_error(error_number, loglist): #Verify if error exists in file
# Notice how we're looping over keys of your dictionary to check if
# an error already exists.
# To access values use loglist[k]
for k in loglist.keys():
if error_number == k:
return True
return False
def dict_error(loglist, error_number, solution): #Puts input errors in dict
# Instead of returning a new dictionary, return the existing one
# with the new error appended to it
loglist[error_number] = solution
return loglist
def verify_file(): #Verify if file exists. Return True if it does
archive = os.path.isfile(PATH)
return archive
def new_error():
# Let's move all the variables to the top, makes it easier to read the function
# Changes made:
# 1. Changed the way we open and read files, now using a context manager (aka with open() as f:
# 2. Added a json parser to store in and read from file in a json format. If data doesn't exist (new file?) create a new dictionary object instead
# 3. Added an exception to signify that an error has been found in the database (this can be removed to add additional logic if you'd like to do more stuff to the error, etc)
# 4. Changed the way we write to file, instead of appending a new line we now override the contents with a new updated dictionary that has been serialized into a json format
found = False
loglist = None
# Open file as read-only using a context manager, now we don't have to worry about closing it manually
with open(PATH, 'r') as f:
# Lets read the file and run it through a json parser to get a python dictionary
try:
loglist = json.loads(f.read())
except json.decoder.JSONDecodeError:
loglist = {}
error_number = input("Error number: ")
if verify_error(error_number, loglist) is True:
found = True
raise Exception('Error exists in the database') # Raise exception if you want to stop loop execution
# Add new solution, or another solution.
solution = str(input("Solution: "))
# This time open in write only and replace the dictionary
with open(PATH, 'w') as f:
loglist = dict_error(loglist, error_number, solution)
# Writes dict on file in json format
f.write(json.dumps(loglist))
def main():
verify = verify_file() #Verify if file exists
if verify == True:
new = str.lower(input("New job Y/N: "))
if new == 'n':
sys.exit()
while new == 'y':
new_error()
new = str.lower(input("New job Y/N: "))
else:
sys.exit()
else:
with open(PATH, "x") as f:
pass
main()
main()
Note that you will have to create a new errordb file for this snippet to work.
Hope this has helped somehow. If you have any further questions hit me up in the comments!
References:
Reading and Writing files in Python
JSON encoder and decoder in Python
I think that there may be a couple of problems with your code, but the first thing that I noticed was that you are saving Error Numbers and Solutions as a dictionary in errorsdb.txt and when you read them back in you are reading them back in as a list of strings:
The line:
loglist = file.readlines()
in new_error returns a list of strings. This means that verify_error will always return False.
So you have a couple of choices:
You could modify verify_error to the following:
def verify_error(error_number, loglist): #Verify if error exists in file
for error in loglist:
if error_number in error:
return True
Although, I think that a better solution would be to load errorsdb.txt as a JSON file and then you'll have a dictionary. That would look something like:
import json
errordb = {}
with open(PATH) as handle:
errordb = json.load(handle)
So here are the full set of changes I would make:
import json
def verify_error(error_number, loglist): #Verify if error exists in file
for error in loglist:
if error_number in error:
return True
def new_error():
errordb = list()
exitsting = list()
with open(PATH) as handle:
existing = json.load(handle)
errordb += existing
error_number = input("Error number: ")
if verify_error(error_number, errordb) == True:
# Add new solution, or another solution.
print("I might do something here.")
else:
solution = str(input("Solution: "))
errordb.append({error_number, solution})
#Writes dict on file
with open(PATH, "w") as handle:
json.dump(errordb, handle)

Append not saving for external file in python

I'm trying to figure out how to make sure that when I run a new dict entry that it actually saves. Before last exception, when you "print(dictio.fullDict3[firstLetter])", it shows the new appended dict entry, but doesn't actually save in the external file called dictio.
The following is the main:
import fileinput
import dictio
from dictio import fullDict3
while True:
try:
srcTxt = input("Input word you want to look up: ")
firstLetter = srcTxt[0]
print(dictio.fullDict3[firstLetter][srcTxt])
except:
try:
queryInput = input('What does '+srcTxt+' mean?: ')
with open("C:\\Users...\\dictio.py", "a"):
dictio.fullDict3[firstLetter].update({srcTxt:queryInput})
print(dictio.fullDict3[firstLetter])
except:
print("error has occured.")
The following is the external file called dictio.py that holds the dictionary:
fullDict3 = {
'0':{
'0data':'0datttaaa',
'0mada':'0mmmaadaa'
},
'a':{
'arbre':'tree',
'arc-en-ciel':'rainbow'
},
'b':{
'bierre':'beer',
'belle':'beautiful'
}
}
You can't change the contents of a module by operating on the module's contents via import. There is no reason to import fullDict3. Instead, store your starting structure in fullDict3.json. Convert that file to a Python object via json.load -- that returns a dict you can change. When you have the updated dict ready to write to disk, save it via json.dump.
Alright. Haven't had much time to code, but finally fixed my issue after some reading and trial an error, for anyone that comes across this for answers, however, there could easily be a cleaner and more efficient way to get it done:
while True:
try:
srcTxt = input("Input word you want to look up: ")
firstLetter = srcTxt[0]
if srcTxt == "ESC":
break
print(dictio.fullDict3[firstLetter][srcTxt])
except:
try:
queryInput = input('What does '+srcTxt+' mean?: ')
with open('C:\\Users...\\dictio.py', 'r') as f:
fullDict3[firstLetter].update({srcTxt:queryInput})
newDict = "fullDict3 = "+json.dumps(fullDict3)
with open('C:\\Users...\\dictio.py', 'w') as f:
f.write(newDict)
f.close()
except:
print("error has occured.")

Saving and Retrieving Python object Attributes values to a file

I require 2 things to be done.
First, take the request object and save the object attribute values
to a file as values of some known keys. This file needs to be editable
after saving, ie, a user can modify the values of the keys(So I used
json format). This is handled in function
save_auth_params_to_file().
Second, get the file contents in a such a format that I can retrieve
the values using the keys. This is handled in function
get_auth_params_from_file.
import json
import os
SUCCESS_AUTH_PARAM_FILE = '/auth/success_auth_params.json'
def save_auth_params_to_file(request):
auth_params = {}
if request is not None:
auth_params['token'] = request.token
auth_params['auth_url'] = request.auth_url
auth_params['server_cert'] = request.server_cert
auth_params['local_key'] = request.local_key
auth_params['local_cert'] = request.local_cert
auth_params['timeout'] = request.timeout_secs
with open(SUCCESS_AUTH_PARAM_FILE, 'w') as fout:
json.dump(auth_params, fout, indent=4)
def get_auth_params_from_file():
auth_params = {}
if os.path.exists(SUCCESS_AUTH_PARAM_FILE):
with open(SUCCESS_AUTH_PARAM_FILE, "r") as fin:
auth_params = json.load(fin)
return auth_params
Question:
Is there a more pythonic way to achieve the 2 things ?
Any potential issues in the code which I have overlooked?
Any error conditions I have to take care ?
There are some things to be noted, yes:
i) When your request is None for some reason, you are saving an empty JSON object to your file. Maybe you'll want to write to your file only if request is not None?
auth_params = {}
if request is not None:
auth_params['token'] = request.token
auth_params['auth_url'] = request.auth_url
auth_params['server_cert'] = request.server_cert
auth_params['local_key'] = request.local_key
auth_params['local_cert'] = request.local_cert
auth_params['timeout'] = request.timeout_secs
with open(SUCCESS_AUTH_PARAM_FILE, 'w') as fout:
json.dump(auth_params, fout, indent=4)
ii) Why not create the dict all at once?
auth_params = {
'token': request.token,
'auth_url': request.auth_url,
'server_cert': request.server_cert,
'local_key': request.local_key,
'local_cert': request.local_cert,
'timeout': request.timeout,
}
iii) Make sure this file is in a SAFE location with SAFE permissions. This is sensitive data, like anything related to authentication.
iv) You are overwriting your file everytime save_auth_params_to_file is called. Maybe you mean to append your JSON to the file instead of overwriting? If that's the case:
with open(SUCCESS_AUTH_PARAM_FILE, 'a') as fout:

Pasring JSON objects that aren't going to be in every record

I've got some data I've acquired from the Twitter Streaming API that I'm trying to parse using python. I've been successful doing this for the most part when parsing out objects that are in ALL records. However, when trying to parse objects that are not be in every record, such as ['coordinates'] or ['entities']['hashtags'] I run into an error.
import json
import sys
def main():
for line in sys.stdin:
line = line.strip()
data = ''
try:
data = json.loads(line)
except ValueError as detail:
continue
if not (isinstance(data, dict)):
## not a dictionary, skip
pass
elif 'delete' in data:
## a delete element, skip for now.
pass
elif 'user' not in data:
## bizarre userless edge case
pass
else:
print "\t".join([
data['created_at'],
data['user']['screen_name'],
data['user']['id_str'],
data['user']['lang'],
data['text'],
data['source']
]).encode('utf-8')
if __name__ == '__main__':
main()
Rather than using data['coordinates'], you could use data.get('coordinates').
Using dict.get(key) will return None if the key isn't in the dictionary, rather than raising a KeyError.

Categories