Can someone help me with my code below? The main purpose of this is to use the data_manager class as a way to store data into a json file.
After being created, a json file named with the specified name, containing a json base, also named with the specified name is created
The major function that handles the majority of the logic is in write_to_json function inside the data_manager class
def write_to_json(self, new_data, base = ""):
There are four major use cases that I am trying to handle:
where match means the item key is found in the file data and base is where we are trying to add the data to (an existing tier / base) (if blank, add it to base)
Case 1 - No match, no base: add to main list
Case 2 - No match, base: add to base
Case 3 - Match, no base: check if value is different and if so, replace value in main list
Case 4 - Match, base, check if value is different and if so, replace value in base list
Right now I have case 1 and 3 working, but I am having issues with 2 and 4.
I have been trying many different ways to code this and keep running into problems.
import os
import sys
import json
class file_manager:
def set_file_contents(self, file_name, contents):
file = open(file_name, "w")
file.write(contents)
file.close()
def set_file_contents_append(self, file_name, contents):
if not os.path.exists(file_name):
open(file_name, 'a').close()
file = open(file_name, "a")
file.write(contents)
file.close()
def get_file_size(self,file_name):
return os.path.getsize(file_name)
def get_file_content_json(self,file_name):
return json.load(open(file_name)) if self.get_file_size(file_name) != 0 else None
class data_manager(file_manager):
data_file = None
json_data = []
data_name = None
def __init__(self,data_name):
self.data_base = data_name
self.data_file = data_name '.json'
self.create_data_file()
def create_base(self,base):
data = {base:[]}
self.set_file_contents(self.data_file,json.dumps(data,indent=4))
def create_data_file(self):
self.create_base(self.data_base)
def check_file_size(self):
print(self.get_file_size(self.data_file))
def check_if_exist(self, data_name):
file_data = self.get_file_content_json(self.data_file)
data_value = False
for item in file_data[self.data_base]:
if data_name in item.keys():
print(f'{data_name}: {item[data_name]}')
data_value = True
return data_value
def get_data_value(self,data_name):
d = self.get_file_content_json(self.data_file)
d = d[self.data_base]
print(data_name)
items = []
for item in self.item_generator(d,data_name):
print(f'returning value = {item}')
items.append(item)
return dict(items[0]) if items else None
def item_generator(self,json_input, lookup_key):
if isinstance(json_input, dict):
for key, value in json_input.items():
if key == lookup_key:
yield {key:value}
else:
yield from self.item_generator(value, lookup_key)
elif isinstance(json_input, list):
for item in json_input:
yield from self.item_generator(item, lookup_key)
def replace_data_value_json(self, file_data, data_name, data_value):
for item in file_data:
if data_name in item.keys():
item[data_name] = data_value
return file_data
def set_data_value(self, data_name, data_value):
file_data = self.get_file_content_json(self.data_file)
for item in file_data[self.data_base]:
if data_name in item.keys():
item[data_name] = data_value
self.set_file_contents(self.data_file,json.dumps(file_data,indent=4))
def view_all_data(self):
file_data = self.get_file_content_json(self.data_file)
print((file_data))
def remove_data_item(self, data_name):
file_data = self.get_file_content_json(self.data_file)
print(file_data)
for element in file_data[self.data_base]:
if data_name in element:
del element[data_name]
self.set_file_contents(self.data_file,json.dumps(file_data,indent=4).replace('{}','').replace('\{\},','') )
def prettyjson(self,data):
return json.dumps(data,indent=4)
def compare_equal(self, value1, value2):
print(f'{value1} really vs {value2}')
return True if str(value1) == str(value2) else False
def write_to_json(self, new_data, base = ""):
file_data = self.get_file_content_json(self.data_file)
#print(f'Data before:\n{json.dumps(file_data,indent=4)}')
base = self.data_base if base == "" else base
#print(list(file_data) - file_data[base])
print(f'Complete file:\n{self.prettyjson(file_data)}')
#file_starting_from_base = list(file_data[data_name])
print('Starting from base')
print(self.prettyjson(file_data[self.data_base]))
file_data_before = ([item for item in file_data if item not in file_data[self.data_base]])
#print(file_data_before)
for data_item in new_data:
match_found = False
index = None
value_from_name = self.get_data_value(data_item)
value_from_name = list(value_from_name) if value_from_name else None
# print(f'before: {value_from_name} {type(value_from_name)} {list(value_from_name)} ')
value_from_name = value_from_name[0] if value_from_name and value_from_name[0] else None
value_from_name_found = True if value_from_name else False
if value_from_name_found:
print(f'found: {value_from_name}')
match_found = True
#OLD METHOD USED TO FIND INDEX
# #if base != self.data_base:
# index = 0
# for item in file_data[self.data_base]:
# print(f'{list(item.keys())[0]} vs {base}')
# if str(base) in list(item.keys())[0]:
# print(f'MATCH FOUND = {base} = {list(item.keys())[0]}')#: {item.values()} {index}')
# match_found = True
# break
# index = 1
# print(index)
# #return
data_single_item = {data_item:new_data[data_item]}
if not match_found:
#Case 1 - No match, no base: add to main list
if base == self.data_base:
file_data[self.data_base].append(data_single_item)
else:
#Case 2 - No match, base: add to base
print(f'ADD {data_single_item} TO {file_data[self.data_base]} starting from {base}')
#possible idea: create base and try again adding values again
#self.create_base(base)
#self.write_to_json(data_single_item,base)
#file_data[self.data_base].append(data_single_item) #broken
#old working method, broken without index
#file_data[self.data_base][index][base].append(data_single_item)
#MATCH FOUND
else:
#Case 3 - Match, no base: check if value is different and if so, replace value in main list
if base == self.data_base:
file_data[base] = self.replace_data_value_json(file_data[base],str(data_item),new_data[data_item])
pass
else:
#Case 4 - Match, base, check if value is different and if so, replace value in base list
print(f'data = {self.get_data_value(data_item)}' )
# print(f'check {new_data[data_item]} vs {list(self.get_data_value(data_item))[0]}')
value_from_name = self.get_data_value(data_item)
value_from_name = list(value_from_name) if value_from_name else None
print(f'before: {value_from_name} {type(value_from_name)} {list(value_from_name)} ')
value_from_name = value_from_name[0] if value_from_name and value_from_name[0] else None
value_from_name_found = True if value_from_name else False
if value_from_name_found and (not self.compare_equal( new_data[data_item], value_from_name ) ):
print(f'{new_data[data_item]} NOT EQUAL TO {value_from_name}')
# change value to new value
#file_data[self.data_base][base].append(data_single_item)
#print(f'add {data_single_item}')
final_output = {self.data_base:file_data[self.data_base]}
self.set_file_contents(self.data_file,self.prettyjson(final_output))
def add_data_single(self, data_name, data_value, base):
new_data_item = {data_name: data_value}
self.write_to_json(new_data_item, base)
def add_data_multiple(self,data,base=""):
self.write_to_json(data,base)
# CREATE 'people.json' AND create json base matching name in file ( { "people": [] } )
test = data_manager('people')
# CREATE 3 ITEMS STARTING IN MAIN BASE
test.write_to_json({'John':[], 'Alex':[], 'Samantha':[]}) # CASE 1
# SHOULD ATTEMPT TO ADD VALUES TO BASE 'john',
# if dictionary key matches, check if key matches
# if key and value match, do nothing and do not overwrite file)
# if key matches and value does not, change the value of the item matching the key starting from base 'John'
# if dictionary key does not match, add full dictionary item to base
test.write_to_json({"Favorite-Food":"tacos" , "Age":45}, "John") # CASE 2
# CREATE
#test.write_to_json({'Example2-Sub1':44},'Example2')
CodePudding user response:
I think/hope you might have some unwanted lists in your json and that when you indicate you are hoping for:
{
"people": [
{"John": [{"favorite-food": "tacos", "Age": 45}]},
{"Alex": []},
{"Samantha": []}
]
}
what you really want is:
{
"people": {
"John": {"favorite-food": "tacos", "Age": 45}
},
{"Alex": {}},
{"Samantha": {}}
}
If that is what you want in the end, then this code based on merging dictionaries via the {**a, **b}
method is the way forward:
import json
import os
class data_manager():
BASE_COLLECTIONS_FOLDER = "./data"
def __init__(self, collection_name):
self.collection_name = collection_name
self.collection_file_path = f"{self.BASE_COLLECTIONS_FOLDER}/{self.collection_name}.json"
self.collection = {}
self.ensure_collection()
self.load_collection()
def ensure_collection(self):
if os.path.isfile(self.collection_file_path):
return
os.makedirs(self.BASE_COLLECTIONS_FOLDER, exist_ok=True)
self.save_collection()
def load_collection(self):
with open(self.collection_file_path, "r", encoding="utf-8") as collection_file:
self.collection = json.load(collection_file)[self.collection_name]
def save_collection(self):
with open(self.collection_file_path, "w", encoding="utf-8") as collection_file:
json.dump({self.collection_name: self.collection}, collection_file, indent=4)
def write_to_json(self, data, key=None):
if not key:
self.collection = {**self.collection, **data}
else:
self.collection[key] = {**self.collection.get(key, {}), **data}
self.save_collection()
people = data_manager("people")
people.write_to_json({"John": {}, "Alex": {}, "Samantha": {}})
people.write_to_json({"Favorite-Food": "tacos", "Age":45}, "John")
people.write_to_json({"Parents": {"Mother": "Britney", "Dad": "Adam"}}, "John")
people.write_to_json({"Parents": {"Mother": "Britney", "Dad": "John"}}, "John")
people.write_to_json({"Bob": {"name": "not bob"}})
people.write_to_json({"Bob": {"name": "bob"}})
people.write_to_json({"Example2-Sub1": 44}, "Example2")
Running this will result in a file who's contents are:
{
"people": {
"John": {
"Favorite-Food": "tacos",
"Age": 45,
"Parents": {
"Mother": "Britney",
"Dad": "John"
}
},
"Alex": {},
"Samantha": {},
"Example2": {
"Example2-Sub1": 44
},
"Bob": {
"name": "bob"
}
}
}