Reputation: 1565
I am trying to add course data to a course, I enter id, name, start and end date, credits. Then I load a file with educations to connect the course, I choose one with the index nr, then I add the education name data to course and finally save the data back to the courses.json file.
But when I look at the course.json file, it lists all the education, not just the course I added with the education name as one of the attributes.
This is my code:
# import packages
import json
from datetime import datetime
def courses():
# Json File Name
filename = 'courses.json'
# Read Json file and load content in data variable
try:
with open("courses.json", "r") as file:
# load content
content = file.read()
# if json file has content save in data variable
if content:
data = json.loads(content)
# else load empty json object in data variable
else:
data = json.loads('{"Courses": [] }')
# exception handling
except FileNotFoundError:
data = json.loads('{"Courses": [] }')
except json.decoder.JSONDecodeError:
data = json.loads('{"Courses": [] }')
# While User wants to add more records
while True:
# input course id
courseId = input("Enter course id: ")
# input course name
course_name = input("Enter course name: ")
# input start date
start_input_date = input("Enter the start date in the format (yyyy-mm-dd): ")
start_date = datetime.strptime(start_input_date, "%Y-%m-%d")
start_date_str = start_date.strftime("%Y-%m-%d")
# input end date
end_input_date = input("Enter the end date in the format (yyyy-mm-dd): ")
end_date = datetime.strptime(end_input_date, "%Y-%m-%d")
end_date_str = end_date.strftime("%Y-%m-%d")
# input course credits
credits = int(input("Enter amount of course credits: "))
# Load the JSON file
with open("educations.json", "r") as file:
# Load the JSON data
data = json.load(file)
# Try to convert the loaded JSON data into a list
try:
educations = list(data["Educations"])
# If the "Educations" key does not exist in the "data" dictionary, assign an empty list to the "educations" variable
except KeyError:
educations = []
# Get the number of educations
num_educations = len(educations)
print("Number of Educations:", num_educations)
# Enumerate through the list of educations and print the index and education name
for index, education in enumerate(educations, start=1):
print(index, education["education_name"])
# Get the index of the education to be chosen
chosen_index = int(input("Enter the index of the education you want to choose: "))
# Check if the chosen index is within the range
if chosen_index > 0 and chosen_index <= num_educations:
# Print the chosen education
print("Chosen Education: ", educations[chosen_index - 1])
else:
print("Invalid index. Please try again.")
education_name = educations[chosen_index - 1]["education_name"]
entry = {'courseId': courseId, 'course_name': course_name, 'start_date': start_date_str, 'end_date': end_date_str, 'credits': credits, 'education_name': education_name}
# Try to append new row in the "Courses" key of the "data" dictionary
try:
data["Courses"].append(entry)
# If the "Courses" key does not exist in the "data" dictionary, create the "Courses" key with an empty list as its value
except KeyError:
data["Courses"]=[]
data["Courses"].append(entry)
# Store all courses in a list
courses = data["Courses"]
print("All courses: ")
for index, course in enumerate(courses):
print(f"{index + 1}. Course:")
for key, value in course.items():
print(f"\t{key}: {value}")
# append data in json file
with open(filename, 'a') as outfile:
json.dump(courses, outfile, indent=4) # using indent to make json more readable
outfile.write('\n')
print("Course added to file successfully!\n")
# ask users for inserting more records or exit program
add_more = input("Do you want to add more courses? (y/n)")
if add_more.lower() == 'n':
break
courses()
The educations.json file has the following content:
{
"Educations": [
{
"education_name": "itsak",
"start_date": "2022-08-22",
"end_date": "2024-05-20",
"education_id": "itsak2023"
},
{
"education_name": "Jamstack",
"start_date": "2023-08-22",
"end_date": "2025-05-20",
"education_id": "Jamst2023"
},
{
"education_name": "Backend developer",
"start_date": "2023-08-22",
"end_date": "2025-05-20",
"education_id": "Backe2023"
}
]
}
The outcome of the file is:
[
{
"courseId": "itstrapi",
"course_name": "Strapi",
"start_date": "2022-08-22",
"end_date": "2022-09-21",
"credits": 45,
"education_name": "Backend developer"
}
]
[
{
"courseId": "itgatsby",
"course_name": "Gatsby",
"start_date": "2022-09-22",
"end_date": "2022-10-21",
"credits": 30,
"education_name": "Jamstack"
}
]
But the desired outcome should be the following:
{
"Courses": [
{
"courseId": "itstrapi",
"course_name": "Strapi",
"start_date": "2022-08-22",
"end_date": "2022-09-21",
"credits": 45,
"education_name": "Backend developer"
},
{
"courseId": "itgatsby",
"course_name": "Gatsby",
"start_date": "2022-09-22",
"end_date": "2022-10-21",
"credits": 30,
"education_name": "Jamstack"
}
]
}
I am getting output now, but not in a proper format though. What have I done wrong?
Upvotes: -1
Views: 94
Reputation: 2565
I've rewrote your script into separate functions such that you can keep track of your logic and data a bit better.
Note that I only write out to the courses.json
once the user indicates that they don't want to add more courses. If you want to save intermediate results, I think the easiest would be to use the .jsonl
format. That format allows you to append a json object on a new line, without it being part of a top-level key.
So instead of this data structure in courses.json
:
{
"courses": [
{"course_id": 1, ...},
{"course_id": 2, ...},
]
}
you would have:
{"course_id": 1, ...}
{"course_id": 2, ...}
This answer shows how you can read .jsonl
back in using Python.
# import packages
import json
from datetime import datetime
def read_courses(fname="courses.json", default_dict=dict(Courses=[])):
# Read Json file and load content in data variable
try:
with open(fname, "r") as file:
# load content
coursedata = json.load(file)
# exception handling
except (FileNotFoundError, json.decoder.JSONDecodeError):
# If no file found or if file is broken JSON load the empty default
coursedata = default_dict
return coursedata
def read_education(fname="educations.json"):
# Re-use the course reader, but with a different file and default dict
edudata = read_courses(fname=fname, default_dict=dict(Educations=[]))
educations = list(edudata["Educations"])
# Print the number of educations
print("Number of Educations:", len(educations))
return educations
def get_user_input():
# input course id
course_id = input("Enter course id: ")
# input course name
course_name = input("Enter course name: ")
# input start date
start_input_date = input("Enter the start date in the format (yyyy-mm-dd): ")
start_date = datetime.strptime(start_input_date, "%Y-%m-%d")
start_date_str = start_date.strftime("%Y-%m-%d")
# input end date
end_input_date = input("Enter the end date in the format (yyyy-mm-dd): ")
end_date = datetime.strptime(end_input_date, "%Y-%m-%d")
end_date_str = end_date.strftime("%Y-%m-%d")
# input course credits
credits = int(input("Enter amount of course credits: "))
user_input = dict(
course_id=course_id,
course_name=course_name,
start_date=[start_date, start_date_str],
end_date=[end_date, end_date_str],
credits=credits,
)
return user_input
def get_selected_education(educations):
edu_selected = False
while edu_selected is False:
# Get the index of the education to be chosen
chosen_index = int(input("Enter the index of the education you want to choose: "))
# Check if the chosen index is within the range
if chosen_index >= 0 and chosen_index <= len(educations):
# Print the chosen education
print("Chosen Education: ", educations[chosen_index])
edu_selected = True
else:
print(
f"{chosen_index} is an an invalid index. Please select a number in the range of 0 and {len(educations)}"
)
education_name = educations[chosen_index]["education_name"]
return education_name
def print_courses(coursedata):
# Store all courses in a list
courses = coursedata["Courses"]
print("All courses: ")
for index, course in enumerate(courses):
print(f"{index + 1}. Course:")
for key, value in course.items():
print(f"\t{key}: {value}")
def courses():
coursedata = read_courses()
educations = read_education()
# While User wants to add more records
while True:
user_input = get_user_input()
for index, education in enumerate(educations):
print(index, education["education_name"])
education_name = get_selected_education(educations=educations)
entry = {
"courseId": user_input["course_id"],
"course_name": user_input["course_name"],
"start_date": user_input["start_date"][1],
"end_date": user_input["end_date"][1],
"credits": user_input["credits"],
"education_name": education_name,
}
# Append new row in the "Courses" key of the "coursedata" dictionary
coursedata["Courses"].append(entry)
print_courses(coursedata=coursedata)
# ask users for inserting more records or exit program
add_more = input("Do you want to add more courses? (y/n)")
if add_more.lower() == "n":
# write data to json file
with open("courses.json", "w") as outfile:
json.dump(coursedata, outfile, indent=4) # using indent to make json more readable
print("Courses added to file successfully!\n")
break
if __name__ == "__main__":
courses()
Output format of courses.json
with above code:
{
"Courses": [
{
"courseId": "1",
"course_name": "2",
"start_date": "1234-06-05",
"end_date": "2345-04-03",
"credits": 12,
"education_name": "Backend developer"
},
{
"courseId": "4",
"course_name": "231",
"start_date": "3456-03-02",
"end_date": "2345-03-02",
"credits": 44,
"education_name": "Backend developer"
}
]
}
Upvotes: 3