As mentioned in previous posts, my team for our capstone project is creating a text-based adventure game using Python. It has been a lot of fun diving into the code and designing this project – and next week we will showcase our first demo! Because of this, our team has been spending a lot of time getting some of the final basic functionalities in place. One of those functionalities is loading data for the rooms in the adventure from external JSON files. And since I have been working on this functionality for the majority of the week, I wanted to share a bit of my process as well as a cool package I plan on using for validating the file structures.
To give context, the foundation of our project rests on game object classes we have created – the Game, Rooms, Doors, and Items. And so, the basic steps for loading up the game from external files are:
- Find all of the JSON room files in the rooms folder.
- For each file, validate that it is structured correctly (more on this later).
- If it is structured correctly, use the data to create a dictionary of Door objects and a dictionary of Item objects.
- Use these dictionaries along with the rest of the data to create a new Room object.
- Add that Room to the rooms dictionary (which is what is returned).
Luckily, loading the external files and creating the objects was not too difficult of a task once we decided on how we wanted the JSON files to be structured. Because of this, the code for the actual load_rooms function itself was fast to write. What took the most time by far was writing the tests for the function once it was complete. I knew that ideally, I wanted a couple of test JSON files to be created automatically for the testing, and then removed after the tests were done running. This led me down a rabbit hole re-learning how to use unittest’s tearDownClass() class method, and the file creation/deletion took a while due in part to having to remind myself how os.path.abspath(path) works. (Hint: it returns a string of the path to the argument relative to the current working directory; and your cwd changes when you are running tests in another folder versus when you are running the main script files.) Once I remembered this, it was mostly smooth sailing getting the rest of the tests written (even if it did take a while).
So far, everything that I have mentioned is something I have done before, and so I was never completely lost. However, there is something new I will be trying for this part of the project that is uncharted territory for me: validating the JSON data for the correct structure.
While finishing up the load_rooms function, I realized it would be important for us to be able to easily verify that each of the Room files we add were using the correct structure. One way to verify the structure would be to manually go through and check for every key – and sure, this would be doable – but there must be a better way, right?
Enter JSON Schema and Python’s jsonschema library.
“When you’re talking about a data format, you want to have metadata about what keys mean, including the valid inputs for those keys. JSON Schema is a proposed IETF standard how to answer those questions for data.”
From the JSON Schema website – Getting Started Step-By-Step
JSON Schema can be used to validate that a data set adheres to a given schema – and the jsonschema Python library is an implementation of this standard. By using this, it will make it much easier for my team and I to ensure that we are not making any major mistakes when adding new rooms to our game. Trying something new like this is always a bit exciting and I am eager to get started on the actual code for it.
Overall, this week has had its fill of triumphs and trials, and while some of the hurdles took a while to get over, I am satisfied with what I learned and accomplished. By this time next week, I hope to have a demo worthy of showcasing on my blog!