how to update a JSON file? - python

I have some code that stores data in a dictionary and than the dictionary is stored in a JSON file:
def store_data(user_inp):
list_of_letters = list(user_inp)
list_of_colons = []
nested_dict = {}
for letter in list_of_letters:
if letter == ':':
list_of_colons.append(letter)
jf = json.dumps(storage)
with open('myStorage.json', 'w') as f:
f.write(jf)
if len(list_of_colons) == 2:
str1 = ''.join(list_of_letters)
list2 = str1.split(':')
main_key = list2[0]
nested_key = list2[1]
value = list2[2]
if main_key not in storage:
storage[main_key] = nested_dict
nested_dict[nested_key] = value
print(storage, '\n', 'successfully saved!')
jf = json.dumps(storage)
with open('myStorage.json', 'w') as f:
f.write(jf)
elif main_key in storage:
if nested_key in storage[main_key]:
print('this item is already saved: \n', storage)
else:
storage[main_key][nested_key] = value
print(storage, '\n', 'successfully saved!')
jf = json.dumps(storage)
with open('myStorage.json', 'w') as f:
f.write(jf)
The problem is that every time I rerun the program and enter new data, the data in the JSON file is replaced by the data entered the last time I ran the program. For example: If I want to store this string: gmail:pass:1234. What my function does is this:
creates a dictionary with the user input and stores it in the JSON file:
{'gmail': {'pass': 1234}}
As long I don't close the program, the data I enter keeps adding to the JSON object. But if I close the program, run it again, and enter new data, the data I stored before is replaced by the data I entered last.
So what I want is that every time I enter a new piece of data to the dictionary, it will add it to the object stored in the JSON file. So if I run the program again and enter this input, gmail:pass2:2343, this is how it should be stored:
{'gmail': {'pass': '1234', 'pass2': '2343'}}
And if I enter this, zoom:id:1234567, I want it to add this to the object inside the JSON file, like so:
{'gmail': {'pass': '1234', 'pass2': '2343'} 'zoom': {'id': '1234567'}}
I really don't know how to fix this, I already researched but I can't find the solution to my specific case.
Hope you understand what I mean. Thank you in advance for your help.

I think this is what you are trying to do:
def update_with_item(old, new_item):
changed = True
top_key, nested_key, value = new_item
if top_key in old:
if nested_key in old[top_key]:
changed = False
print("This item is already saved: \n", storage)
else:
old[top_key][nested_key] = value
else:
old[top_key] = {nested_key: value}
return old, changed
def main():
stored = json.load(open('myStorage.json'))
old, changed = update_with_item(stored, list2)
if changed:
jf = json.dumps(old)
with open('myStorage.json', 'w') as f:
f.write(jf)
print(storage, '\n', 'successfully saved!')
I'm also not sure how you looping over the code in main, or where the list2 variable is coming from. The main function here will need to be updated to how you are looping over creating the new values etc.
The update_with_item function should resolve the issue you are having with updating the dictionary though.

Related

Why is this python function not reading my json File string properly?

So I have a unique player ID string that is stored in a JSON file after it detects on start-up that the player is new to the game.
def checkIfPlayerIsNew():
if os.path.exists("myJson.json"):
print('file exists')
k = open('myPlayerIDs.json')
print(k.read())
#print("This is the k value: {}".format(code))
#code = json.dumps(k)
getData(k.read())
else:
print('file does not exist')
f = open('myJson.json', 'x') #creates the file if it doesn't exist already
f.close()
file = open('myPlayerIDs.json', 'w')
file.write(json.dumps(str(uuid.uuid4())))
file.close
checkIfPlayerIsNew()
Now, if it detects that the player is not new it gets the ID from the JSON File and passes it to the get data function below
def getData(idCode = "X"):
print('the id code is this: {}'.format(idCode))
outputFile = json.load(open('myJson.json'))
for majorkey, subdict in outputFile.items():
if majorkey == idCode:
for subkey, value in subdict.items():
print('{} = {}'.format(subkey, value))
#playerData[subkey] = value
else:
print("ID Does not match")
break
The problem is that when I check the id code in the get data function it prints out a blank space as if the id code has been changed to nothing (which I can't figure out why it has done that) and prints this out to the terminal:
The playerID JSON File:
You can't read() a file twice without seeking back to the start. The right thing to do here is to read the file into a variable:
if os.path.exists("myJson.json"):
print('file exists')
# Read file into a variable and use it twice
with open('myPlayerIDs.json', 'r') as k:
data = k.read()
print(data)
getData(data)
#...

How to create a dictionary key inside a another dictionary with the previous values of old dictionary key

So I am parsing through a json file with many dictionary values and keys. I want to be able to create a new dictionary key value within another dictionary and take all the contents from the old dictionary and put it within the new dictionary.
Here is what the original json file looks like:
{"runContext": {"isAdmin": "false", "isSimulated":false, "customerId": "132", "acId": "1445017", "id":"magtest1"}}
Here is what the modified json file should look:
{"context": {"user":{"id":"magtest1", "isSimulated":false, "customerId":"132", "isAdmin":false "acID": "1445017}}}
I had to change the name of runContext to context and then after that I essentially need to create a new object called user and store all the previous contents with context and store it within the new object user. I am opening the original json file using its path name however I am having trouble taking the contents from context and putting into a new object called user
Here is the script I wrote:
def jsonparse():
user_path= input("Please enter path name:")
with open(user_path) as f:
x = f.read()
jObject = json.loads(x)
context = jObject['runContext']
jObject['context']= jObject.pop('runContext')
jObject['context']['user'] = {}
jObject['context']['user'] = context
print jObject
if __name__ == '__main__':
jsonparse()
My issue is when I try to print it out, it looks like this
{"context":{user:{...}
It doesn't output out any values for user
Any help on this is appreciated since I'm new to JSON. Thanks!
Your context is not defined. It should be:
context = jObject.pop('runContext')
jObject['context']['user'] = {}
jObject['context']['user'] = context
Do this:
def jsonparse():
user_path= input("Please enter path name:")
with open(user_path) as f:
x = f.read()
jObject = json.loads(x)
context = jObject.pop('runContext')
jObject['context'] = {}
jObject['context']['user'] = context
print jObject
if __name__ == '__main__':
jsonparse()
Before on jObject['context']= jObject.pop('runContext') you had the dictionary that you need in jObject['context']['user'] in jObject['context'].
Now after context = jObject.pop('runContext') the jObject will be empty({}) and then you will add the keys jObject['context'] = {} and the context jObject['context']['user'] = context
Hope that helps.

Trying to implement a cache on load of this file

The cache would have an initial size of 20 elements and upon reaching its limit, to add any new element it would remove the least recently accessed element. On shutdown it should store the cached data back to the file. The data should be stored in the cache according to a caching strategy. Provide options for cache CRUD. Testing Data set : records of student.
import json
from collections import OrderedDict
import time
import os
if os.path.exists("qwerty.json"):
record = json.load(open("qwerty.json", "r"), object_pairs_hook=OrderedDict)
else:
record = OrderedDict({})
fo = open("foo.txt", "wb")
x = list(record.items())[:20]; x2 = sorted(x, key=lambda k: k[1]['time'], reverse=True)
print(x2)
command = ""
while command != 'exit':
command = input('Enter a command(options: create,read,save): ')
if command == "create":
name = input('Enter name of the Student:')
p = input('Student ID: ')
a = input('Class: ')
n = input('Marks: ')
time = time.time()
record[name] = {'Student ID:': p, 'Class:': a, 'Marks': n, 'time': time }
elif command == 'read':
z = json.load(open("qwerty.json", "r"), object_pairs_hook=OrderedDict)
print(z)
elif command == 'save':
json.dump(record, open('qwerty.json', "w"))
fo.close()
You can actually maintain order with a single file, using a combination of json and collections.OrderedDict.
Your initial setup is like so:
from collections import OrderedDict
phone_book = OrderedDict({})
When creating, add elements into an ordered dict and then dump it as JSON. The order of keys is preserved. After you declared phone_book like above, the rest of the code for create remains the same. Note that when you write to the file, you don't close it, so you can't read the contents later. This should be replaced with something like:
import os
if os.path.exists("qwerty.json")
phone_book = json.load(open("qwerty.json", "r"), object_pairs_hook=OrderedDict)
else:
phone_book = OrderedDict({})
command = ""
while command != 'exit':
command = input('Enter a command(options: create,read,save): ')
if command == "create":
...
elif command == 'read':
...
elif command == 'save':
json.dump(phone_book, open('qwerty.json', "w"))
For reading, you'll have to make some changes:
elif command == 'read':
z = json.load(open("C:\\Users\\qwerty.txt", "r"), object_pairs_hook=OrderedDict)
...
This loads the dict in the order the keys were stored. You can now call list(z.items())[-20:] to get only the last 20 items. Also, when reading a particular key, you update its "last-read-time" by deleting and recreating it:
import copy
key = ...
temp = copy.copy(z[key])
del z[key]
z[key] = temp
This will update the position of key in the dict. This should be enough for you to implement the rest yourself.

Key found in dictionary that shouldn't exist

Hey having some issues here. I am reading a file with keys and translations, a typical line in the file is like so:
"welcome-screen" = "Welcome to the app!"
The file also has a language prefix stored in lang_key, e.g. lang_key = eng.
Currently I am trying to build a dict:
strings_dict = {}
f = open(os.path.join(root, file), 'r')
for line in f:
strings = line.split('"')[1::2]
if len(strings) == 2:
if strings[0] in strings_dict:
entry = strings_dict[strings[0]]
entry[lang_key] = strings[1]
strings_dict[strings[0]] = entry
print("modified entry")
else:
entry = {lang_key: strings[1]}
strings_dict[strings[0]] = entry
print("made entry")
The line.split pulls the words out of the quotation marks. e.g the line above becomes [welcome-screen, Welcome to the app!]. The key is the first word welcome-screen if it's already in the dictionary I want to pull its value out of the dictionary (the value is also a dictionary) and add an item for the key lang_key. If the key is not already in the dictionary I want to create a new entry. However when debugging it seems to print `modified entry" every single time. Not once does it create a new entry. Why is this happening?

Python: Reading individual elements of a file

I am attempting to read in individual elements of a file. In this example, the first element of each line is to be the key of a dictionary. The next five elements will be a corresponding value for said key in list form.
max_points = [25, 25, 50, 25, 100]
assignments = ['hw ch 1', 'hw ch 2', 'quiz ', 'hw ch 3', 'test']
students = {'#Max': max_points}
def load_records(students, filename):
#loads student records from a file
in_file = open(filename, "r")
#run until break
while True:
#read line for each iteration
in_line = in_file.readline()
#ends while True
if not in_line: break
#deletes line read in
in_line = in_line[:-1]
#initialize grades list
grades = [0]*len(students['#Max'])
#set name and grades
name, grades[0], grades[1], grades[2], grades[3], grades[4] = in_line.split()
#add names and grades to dictionary
students[name] = grades
print name, students[name]
filename = 'C:\Python27\Python_prgms\Grades_list.txt'
print load_records(students, filename)
The method I have now is extremely caveman, and I would like to know what the more elegant, looping method would be. I have been looking for a while, but I can't seem to find the correct method of iteration. Help a brotha out.
Another way of doing it:
def load_records(students, filename):
with open(filename) as f:
for line in f:
line = line.split()
name = line[0]
students[name] = map(int, line[1:])
print name, students[name]
It seems a bit strange that the student dictionary contains both the scores and a parameter #Max though - a key has two meanings, is it a student's name or parameter's name? Might be better to separate them.
I had an assignment similar to this last year.
def load_records(students, filename):
file = open(filename, 'r')
s = ""
while s != None: # loop until end of file is reached
s = file.readline()
# manipulate s how you need
Also, you should use inline comments like above, it makes the code much easier to read compared to how you have it now.

Categories

Resources