0

I am learning python, and I have two json files. The data structure in these two json files are different structures.

I start by importing both of the json files. I want to choose a course from the courses dict, and then add it to a specific education in the educations dict. What I want to solve is via user input choose a key from the first dict, and then within a while loop, so I can add choose a key from the second dict to be added to the dict chosen from the first dict.

I am able to add the dict from the second dict to the one first as a sub dict as I want to, but with the update method it overwrites all previous values.

I have used the dict.update() method so not to overwrite previous values. I then want to write back the updated dict back to the first json file.

My code works partially, I am able to add a course to a educations, but it overwrites all previous courses I chose to add to a specific education.

This is the content of the first json file:

{
    "itsak22": {
        "edcuationId": "itsak22",
        "edcuation_name": "cybersecurityspecialist"
    },
    "feu22": {
        "edcuationId": "feu22",
        "edcuation_name": "frontendutvecklare"
    }
}

This is the content of the second json file:

{
    "sql": {
        "courseId": "itsql",
        "course_name": "sql",
        "credits": 35
    },
    "python": {
        "courseId": "itpyt",
        "course_name": "python",
        "credits": 30
    },
    "agile": {
        "courseId": "itagl",
        "course_name": "agile",
        "credits": 20
    }
}

And this is my python code:

import json

# Load the first JSON file of dictionaries
with open('edcuations1.json') as f:
    first_dicts = json.load(f)

# Load the second JSON file of dictionaries
with open('courses1.json') as f:
    second_dicts = json.load(f)

# Print the keys from both the first and second JSON files
print("All educations:", first_dicts.keys())
print("All courses:", second_dicts.keys())

# Ask for input on which dictionary to add to which
first_key = input("Which education would you like to choose to add courses to? (Enter 'q' to quit): ")

while True:
    second_key = input("Which course would you like to add to education? (Enter 'q' to quit)")
    if second_key == 'q':
        break

    # Create a sub-dictionary named "courses" in the specific dictionary of the first file
    if "courses" not in first_dicts[first_key]:
        first_dicts[first_key]["courses"] = {}
    first_dicts[first_key]["courses"].update(second_dicts[second_key])
    #first_dicts = {**first_dicts, **second_dicts}
    #first_dicts.update({'courses': second_dicts})



# Update the first JSON file with the new dictionaries
with open('edcuations1.json', 'w') as f:
    json.dump(first_dicts, f, indent=4)
mkrieger1
  • 19,194
  • 5
  • 54
  • 65
user2371684
  • 1,475
  • 5
  • 20
  • 45
  • Does this answer your question? [Dictionary merge by updating but not overwriting if value exists](https://stackoverflow.com/questions/6354436/dictionary-merge-by-updating-but-not-overwriting-if-value-exists) – mkrieger1 Jan 31 '23 at 16:34

2 Answers2

1

I'm not entirely sure how your desired result should look like but I think your dictionary courses should be a list and not a dictionary.

Then you can do

if "courses" not in first_dicts[first_key]:
    first_dicts[first_key]["courses"] = []
first_dicts[first_key]["courses"].append (second_dicts[second_key])

And your result looks like this if you add all courses to itsak22

{
    "itsak22": {
        "edcuationId": "itsak22",
        "edcuation_name": "cybersecurityspecialist",
        "courses": [
            {
                "courseId": "itsql",
                "course_name": "sql",
                "credits": 35
            },
            {
                "courseId": "itpyt",
                "course_name": "python",
                "credits": 30
            },
            {
                "courseId": "itagl",
                "course_name": "agile",
                "credits": 20
            }
        ]
    },
    "feu22": {
        "edcuationId": "feu22",
        "edcuation_name": "frontendutvecklare"
    }
}
flappix
  • 2,038
  • 17
  • 28
  • Yes, your solution worked out. So does this mean that adding to a empty dictionary won't work, but with a empty list? – user2371684 Jan 31 '23 at 18:12
  • A second thought on this, what if I add a course dictionary that already exists in the list of dictionaries – user2371684 Jan 31 '23 at 20:44
  • 1
    @user2371684 You could also use a dictionary but in this case you have to provide key. You could use ```courseId``` for this or ```course_name```. For a list you dont have to provide a key, python will automatically assign an incrementing number as key like ```0```, ```1```, ```2```, ... – flappix Jan 31 '23 at 21:15
  • 1
    @user2371684 To your second question: In this case you would have multiple instances of this course in your list. To avoid this you have to check if this course is already part of the list before adding it. – flappix Jan 31 '23 at 21:16
1

Here is my approach:

import json

# Load the first JSON file of dictionaries
with open("educations1.json") as f:
    educations = json.load(f)

# Load the second JSON file of dictionaries
with open("courses1.json") as f:
    courses = json.load(f)

# Print the keys from both the first and second JSON files
print("All educations:", educations.keys())
print("All courses:", courses.keys())

# Ask for input on which dictionary to add to which
education_key = input(
    "Which education would you like to choose to add courses to? (Enter 'q' to quit): "
)
education_courses = educations[education_key].setdefault("courses", {})

while True:
    course_key = input(
        "Which course would you like to add to education? (Enter 'q' to quit): "
    )
    if course_key == "q":
        break

    education_courses[course_key] = courses[course_key]


# Update the first JSON file with the new dictionaries
with open("educations1.json", "w") as stream:
    json.dump(educations, stream, indent=4)

A few notes

  • I fixed the typos: edcuations1.json -> educations1.json
  • Instead of generic names such as first_dicts, first_keys, ... I use more descriptive names

How it works

The heart of my solution is on this line:

education_courses = educations[education_key].setdefault("courses", {})

Which is the equivalent of:

if "courses" not in educations[education_key]:
    educations[education_key]["courses"] = {}
education_courses = educations[education_key]["courses"]

The setdefault method basically assign a value (an empty dictionary in this case) to a dictionary if the key ("courses" in this case) is absent.

Hai Vu
  • 37,849
  • 11
  • 66
  • 93