pythonjsonriot-games-api

Append New Data to JSON


I'm struggling to append new data to a JSON. I simply want to call JSON data from an API, and put it into a JSON file under "matches". I am creating a blank JSON file containing the following and just going from there.

{
    "matches": [
    ]
}

Here is my code, though I suspect only the last line is important:

print ("No records found...\n Creating new match history bank.")
file_handle = open(all_matches_index, "w+")
file_handle.write('{\n    "matches": [\n    ]\n}')

for game_id in game_ids:
        full_match_data = watcher.match.by_id(my_region, game_id)
        #this is the problem line:
        file_handle.write(json.dumps({"matches" : full_match_data }, sort_keys=True, indent = 4, separators=(',', ': ')))

I have tried a litany of different solutions and nowhere online seems to address this, or at least I am not understanding what I am reading. I know its a simple problem but I can't solve it.

Some examples of what I have tried:

file_handle.write(json.dumps(full_match_data["matches"], sort_keys=True, indent = 4, separators=(',', ': ')))

file_handle["matches"].write(json.dumps(full_match_data, sort_keys=True, indent = 4, separators=(',', ': ')))

file_handle["matches"] = {**full_match_data, file_handle["matches"] sort_keys=True, indent = 4, separators=(',', ': ')))}

file_handle.write(json.dumps({"matches" : [full_match_data]}, sort_keys=True, indent = 4, separators=(',', ': ')))

file_handle.write(json.dumps(["matches" {full_match_data}], sort_keys=True, indent = 4, separators=(',', ': ')))

Edit 1: Changes based on the response from Pranav Hosangadi,

First of all, thank you for your response, it contains far more information than a simple fix and this really helps me as I learn.

I changed my code so that it now looks as follows:

file_handle = open(all_matches_index, "w+")
file_handle.write('{\n    "matches": [\n    ]\n}')
file_handle.close()


matches = []
for game_id in game_ids:
    full_match_data = watcher.match.by_id(my_region, game_id)
    matches.append(full_match_data)

with open(all_matches_index, "w") as file_handle:
    json.dump(file_handle, {"matches": matches})
    
    file_handle.close

Unfortunately, it doesn' work. It seems to think for quite a while (being an intel pentium) and then returns an empty file?

Running it a second time fills the file with:

{
    "matches": [
    ]
}

Would you be able to tell me where I am going wrong?

Once I get it to work I will switch to the pythonic way of doing it. Many thanks.


Solution

  • Why write to the file every time you get a result from the API? Just append new full_match_data to a list and write it once after you have them all. Also note that json.dump can write to a file handle directly, no need to dumps into a string and then write that string to a file.

    matches = []
    for game_id in game_ids:
        full_match_data = watcher.match.by_id(my_region, game_id)
        matches.append(full_match_data)
    
    with open(all_matches_index, "w") as file_handle:
        json.dump({"matches": matches}, file_handle)
    

    You can replace the loop with a list comprehension for more pythonic way:

    matches = [watcher.match.by_id(my_region, game_id) for game_id in game_ids]
    

    Re. edits in question:

    There was an error in my original answer. json.dump expects json.dump(data, file_handle). See the updated answer.


    file_handle = open(all_matches_index, "w+")
    file_handle.write('{\n    "matches": [\n    ]\n}')
    file_handle.close()
    

    This part of your code is unnecessary. All it does is write an empty file. The with... block in the code later is supposed to overwrite this anyway.


    matches = []
    for game_id in game_ids:
        full_match_data = watcher.match.by_id(my_region, game_id)
        matches.append(full_match_data)
    

    This is the part that creates the list


    with open(all_matches_index, "w") as file_handle:
        json.dump({"matches": matches}, file_handle)
    

    This is the part that writes the data to the file. Using with creates a context manager that automatically closes the file for you once the with block ends. You can find lots of information on the web.


        file_handle.close
    

    This is (a) unnecessary because the context manager handled closing the file anyway, and (b) wrong, because you need to call the function, so file_handle.close() like you did earlier.