undo Back to Articles Index

Importing JSON in GameMaker Studio 2

By: John Kidd Jr on 03/06/2023 06:55 PM

What is JSON?

From the official website: "JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write. It is easy for machines to parse and generate. It is based on a subset of the JavaScript Programming Language Standard ECMA-262 3rd Edition - December 1999. JSON is a text format that is completely language independent but uses conventions that are familiar to programmers of the C-family of languages, including C, C++, C#, Java, JavaScript, Perl, Python, and many others."

Basically, it's a way of formatting data in text that is not super hard to read for humans, and easy to read for computers. It's used widely for desktop applications, interchanging data between websites, and more.

Why import data from JSON?

Because JSON is easy to read for both humans and computers, that makes it ideal for storing data we use in our game. While this article will be focusing it's effort on implementing this in GameMaker Studio 2, JSON is a very useful format that can be used in almost any game engine.

The important part, is the human readability. If you notice an issue with your game that could be related to the data, it's important that you can quickly sift through the file and find the potential issue. Additionally, because JSON is easy to generate and consume... we can create tools for our designers to use that outputs a simple JSON file. This keeps people not trained in using the game engine, out of places they could easily and accidentally break something!

Code

Time to start coding!

Because GameMaker Language is weak-typed, we can jump right into programming without having to worry about the structure of our objects yet. This is both a blessing and a curse... this means any JSON file can be loaded in by our code, so be careful if you plan to use JSON for more than a single type of data.

To start with create a new object (you can do this as a script as well, but you would need to call your script from somewhere). On the new object, add a "Create" event that we can use to enter our code. It should look something like this:

Our new object with a create step!

Now, double-click on the event to open a code window (it may have opened immediately when you created the event).

For our code we will need to get the path to where our data is stored. It's easiest to use the built-in "datafiles" directory, since GameMaker will provide us with a built-in variable to use. Once we have our working path, we want to start a search for files with the .json extension on them. Then we'll start a loop where we process the files until we don't find any more. Finally we close off the operations. Let's see it in code:

//store a variable with the file path
var filePath = working_directory + "/jsondata/";

//get the first file with the .json extension
var fileName = file_find_first(filePath + "*.json", fa_directory);

//loop until the filename is blank
while(fileName != "")
{
    //create a variable to store data in
    var importedJson;
	var fullPath = filePath + fileName;
	
    //make sure we don't try this unless it exists!
	if (file_exists(fullPath))
	{
		var json = "";
	
        //create a file stream
		var file = file_text_open_read(fullPath);
	
        //read to the end of file
		while(!file_text_eof(file))
		{
			json += file_text_readln(file);
		}
	
        //close the file
		file_text_close(file);
	
        //parse the json into a struct
		importedJson = json_parse(json);
	}
	
    //process the file here

    //get the next json file
	fileName = file_find_next();
}

//close our find operation
file_find_close();

As you can see, there is a section specifically for where to handle your custom importing logic. This is the place where you would call a script to setup an object, or just store this newly created object somewhere to use later.

What if you need to store 2 or more different kinds of data in JSON? Well, if you do that I would recommend you add a field in your JSON at the top level that tells you the type of the data. Something like this:

{
    "DataType": "CharacterData",
    //more data goes here
}

Assuming we had CharacterData and LevelData as our types, we could add those in right where the comment for "process the file here" is at.

//you can do this as a series of "if" statements, or as a switch

//if you have more than 3 different kinds of files, or plan to
//you should use a switch statement instead of an "if"
if(importedJson.DataType == "CharacterData") {
    //run our character setup script
    SetupCharacter(importedJson);
}
else if(importedJson.DataType == "LevelData") {
    //run our level setup script
    SetupLevel(importedJson);
}
//add an optional else statement here for the default

The last thing we want to do is make sure this object gets created somewhere so our code will execute! Depending on the type of data you are loading, you may want to place this in a more appropriate place (like a level, so the data isn't loaded until the level itself is), but for simplicity we'll add ours to our default room (it has a little house next to it).

Home room?

Simply drag the object anywhere into the room... and you're done! You'll see the object appear as a question mark because we didn't assign a sprite to it, but it will be invisible in the actual game!

Alone in the dark

What happens to the JSON when I compile?

So what happens with these files when you compile and ship your game? Well if you placed them in the datafiles folder in your project like in the example, then they will be compiled into the game as a resource. That means you won't have to distribute any additional files with your game, it'll all be built in!

More Reading

undo Back to Articles Index