Opens an external site in a new window
Pride Month Hold my hand 🫱🏾‍🫲🏼
RODNEY LAB
  • Home
  • Plus +
  • Newsletter
  • Links
  • Profile
RODNEY LAB
  • Home
  • Plus +
  • Newsletter
  • Links

Parsing JSON Game Data: Read JSON in C++ GameDev 🕹️ # Parsing JSON Game Data: Read JSON in C++ GameDev 🕹️ #

blurry low resolution placeholder image Parsing JSON Game Data
  1. Home Rodney Lab Home
  2. Blog Posts Rodney Lab Blog Posts
  3. C++ C++ Blog Posts
<PREVIOUS POST
NEXT POST >
LATEST POST >>

Parsing JSON Game Data: Read JSON in C++ GameDev 🕹️ #

Updated 11 months ago
6 minute read
Gunning Fog Index: 6.2
Content by Rodney
blurry low resolution placeholder image Author Image: Rodney from Rodney Lab
SHARE:

💾 JSON Game Data #

In this post, we look at parsing JSON game data using the C++ nlohmann/json library, written in C++11. I am working on a clone of the Arkanoid arcade from the 1980s, and decided using a JSON file was the best way to store and load game configuration data. Here, I run through my first impressions of the library.

Although the focus is a game that uses raylib for rendering, the code has wider applications in game code as well as wider C++ applications.

This is a learning in public post, so I would love to hear your opinion, especially if there is something here I might be able to improve on.

🧱 What we’re Building #

I have been working on a C++ clone of the Arkanoid arcade game using raylib for rendering. In the original game, the player has to destroy rows of bricks at the top of the screen. The rows are populated with bricks of different colours, and destroying bricks of some colours earns more point than others. Most bricks take a single hit to destroy, though silver bricks need two hits and gold bricks are indestructible.

blurry low resolution placeholder image Parsing JSON Game Data: Screen capture shows a retro arcade game with pixelated fonts and bright colours.  Bricks are arranged in rows at the top of the screen, each row a different colour, the lowest row is green and the highest silver.  Below the brick, a red ball looks like it might be about to collide with one of the green bricks in the lowermost row.
Parsing JSON Game Data: Arkanoid clone game

Taking those scoring details and maintainability into account, I decided to put the brick properties into a JSON file loaded on setup. I picked the nlohmann/json library to parse JSON. There are other C++ JSON libraries available , and I settled on this one mostly because it looked popular and has good CMake integration.

I am loading JSON at initialization, and the JSON config file is small, so speed was not at the top of my wish list. If you are concerned about speed, for your project though, see these benchmarks comparing C and C++ JSON libraries .

In the rest of the post, we take a quick look at eh JSON file, the CMake nlohmann/json config and then, some code snippets to see the library in action. You will find a link, further down, to the project repo, which has full code examples.

JSON Config File #

I placed the file in an assets directory at the root of the project:

assets/level_bricks.json
json
    
{
"bricks": [
{ "colour": "white", "value": 50 },
{ "colour": "orange", "value": 60 },
{ "colour": "cyan", "value": 70 },
{ "colour": "green", "value": 80 },
{ "colour": "red", "value": 90 },
{ "colour": "blue", "value": 100 },
{ "colour": "magenta", "value": 110 },
{ "colour": "yellow", "value": 120 },
{ "colour": "silver", "value": 50, "hitsToDestroy": 2 },
{ "colour": "gold", "value": 0, "hitsToDestroy": 999 }
],
"levelBricks": [
{ "level": 1, "rows": ["silver", "red", "blue", "orange", "magenta", "green"] }
]
}

nlohmann/json supports importing data with default values, so although I included hitsToDestroy values for silver and gold bricks, I omitted the value for the other coloured bricks. For those I will import with a default value of 1.

⚙️ CMake nlohmann/json Config #

The CMake integration was quite straightforward. I use CPM (instead of CMake FetchContent) in the project to manage third-party libraries, and the CPM repo includes an nlohmann/json example .

CMakeLists.txt
cmake
    
1 include(cmake/CPM.cmake)
2 cpmaddpackage("gh:nlohmann/json#9cca280a4d0ccf0c08f47a99aa71d1b0e52f8d03"
3 )# v3.11.3
4
5 add_library(FileSystem_lib STATIC "${PROJECT_SOURCE_DIR}/src/file_system.cpp")
6 set_target_properties(FileSystem_lib PROPERTIES CXX_CLANG_TIDY
7 "${CLANG_TIDY_COMMAND}")
8 target_link_libraries(
9 FileSystem_lib
10 nlohmann_json::nlohmann_json
11 arkanoid_compiler_flags)
12 target_compile_definitions(
13 FileSystem_lib PUBLIC ASSETS_PATH="${CMAKE_CURRENT_SOURCE_DIR}/assets/")

Observations:

  • You can download the CPM.cmake file from the CPM repo , and place it in a project cmake directory.
  • With CPM you can pick a tag from a repo, just using its tag name, though I prefer to use commit hashes, as above (line 2).
  • I included the ASSETS_PATH definition in line 12-13 to make the path available in source code (see examples, further down).

🖥️ Adding JSON parsing code #

I am used to serde for parsing JSON in Rust , which has quite detailed type checking. nlohmann/json is a little more relaxed in this regard, though I suppose an advantage is that you can get going quicker, and it might suit workflows with high levels of iteration.

Parsing JSON Game Data #

src/file_system.h
cpp
    
1 #include "file_system.h"
2
3 #include <nlohmann/json.hpp>
4 #include <nlohmann/json_fwd.hpp>
5 #include <spdlog/spdlog.h>
6
7 #include <cstddef>
8 #include <fstream>
9 #include <map>
10 #include <stdexcept>
11 #include <string>
12 #include <string_view>
13
14
15 void parse_level_bricks_file(std::string_view json_path,
16 nlohmann::json &json_data)
17 {
18 std::ifstream json_file{json_path.data()};
19 if (!json_file)
20 {
21 spdlog::error("Unable to open {} for reading.", json_path);
22 }
23
24 try
25 {
26 json_data = nlohmann::json::parse(json_file);
27 }
28 catch (nlohmann::json::parse_error &exception)
29 {
30 spdlog::error("Error parsing JSON from `{}`: {}.",
31 json_path,
32 exception.what());
33 }
34 }

To parse the JSON file, I just called nlohmann::json::parse(), passing in the file std::ifstream. That function returns an nlohmann::json object with the JSON data that has convenient access methods (see following section). I used the spdlog library for logging.

The nlohmann/json parse function throws an exception  if it encounters an unexpected token in the JSON or encounters an issue in converting input bytes to Unicode (the library has full UTF-8 support and partial UTF-16 support).

Using the ASSETS_PATH variable set in the CMakeLists.txt file above, I can create a variable for the path to my JSON data file (assets/level_bricks.json), in C++ source code, thus:

    
const std::string json_path{ASSETS_PATH "level_bricks.json"};

Reading Parsed Game Data #

There are three common methods for accessing JSON data returned by the nlohmann:json::parse function:

  • data["KEY"] for unchecked access,
  • data.at("KEY") for checked access; and
  • data.value("KEY", <default_value>) to return the provided default value when the key is absent.

Unchecked Element Access #

The first, like the std::map accessor can be used to mutate the JSON data. It returns null if the key is absent.

src/file_system.cpp
cpp
    
1 const int level_1_rows{
2 static_cast<int>(json_data["levelBricks"][0]["rows"].size())};
3 if (level_1_rows == 0)
4 {
5 spdlog::error("Error in JSON data from `{}`: expected at least one row "
6 "of bricks in levelBricks[0].rows.",
7 json_path);
8 }

I used the [] operator here to access the root level levelBricks array, then again, to index into the rows field of the array’s first element.

You also see the size method in use here, which will return the length of a JSON array, the number of fields in a JSON object or 1, if it is called on a scalar. It returns 0 if called on a null nlohmann::json object, which happens if you access a field that does not exist in the parsed data.

Checked Element Access #

src/file_system.h
cpp
    
1 const auto bricks_json_data = json_data["bricks"];
2
3 for (const auto &element : bricks_json_data)
4 {
5 try
6 {
7 const std::string colour_field{element.at("colour")};
8 // TRUNCATED...
9 }
10 catch (const std::out_of_range & /* exception */)
11 {
12 spdlog::error(
13 "Error in JSON data from `{}`: unknown BrickType: '{}'.",
14 json_path,
15 std::string(element));
16 throw exception;
17 }
18 }

This time I use checked access, via the at method (in line 7). This throws an exception if the colour field is missing. The library also provides a C++11 range-based loop access to elements, as used in line 3.

Value or Default Element Access #

Finally, we have value or default access. For the game, most bricks only need one hit to be destroyed, and the silver needs two, while the gold brick is indestructible. Rather than add a value for this field for all bricks, I decided to set the value to 1, as a default when it is absent.

src/file_system.h
cpp
    
1 const auto bricks_json_data = json_data["bricks"];
2
3 for (const auto &element : bricks_json_data)
4 {
5 const int hits_to_destroy{element.value("hitsToDestroy", 1)};
6 // TRUNCATED...
7 }

The value member on the nlohmann::json object (used in line 5) does exactly what I am looking for here. Of course, it works similarly for string fields, for example.

Please enable JavaScript to watch the video 📼

Parsing JSON Game Data: Arkanoid clone game

🗳 Poll #

What are your thoughts on nlohmann/json
Voting reveals latest results.

🙌🏽 Parsing JSON Game Data: Wrapping Up #

In this post on parsing JSON game data, we saw how you might use nlohmann/json to load data in a C++ game. More specifically, we saw:

  • how to set up nlohmann/json CMake config;
  • the main JSON data object access methods; and
  • parsing and other useful methods provided by the library.

I hope you found this useful. As promised, you can get the full project code on the Rodney Lab GitHub repo . Do let me know if you found this content useful and would like to see more similar content. Also reach out if there is anything I could improve to provide a better experience for you.

🙏🏽 Parsing JSON Game Data: Feedback #

If you have found this post useful, see links below for further related content on this site. Let me know if there are any ways I can improve on it. I hope you will use the code or starter in your own projects. Be sure to share your work on X, giving me a mention, so I can see what you did. Finally, be sure to let me know ideas for other short videos you would like to see. Read on to find ways to get in touch, further below. If you have found this post useful, even though you can only afford even a tiny contribution, please consider supporting me through Buy me a Coffee.

Finally, feel free to share the post on your social media accounts for all your followers who will find it useful. As well as leaving a comment below, you can get in touch via @askRodney on X (previously Twitter) and also, join the #rodney  Element Matrix room. Also, see further ways to get in touch with Rodney Lab. I post regularly on Game Dev as well as Rust and C++ (among other topics). Also, subscribe to the newsletter to keep up-to-date with our latest projects.

Thanks for reading this post. I hope you found it valuable. Please get in touch with your feedback and suggestions for posts you would like to see. Read more about me …

blurry low resolution placeholder image Rodney from Rodney Lab
TAGS:
C++GAMING

Related Post

blurry low resolution placeholder image C++ Game Utility Libraries: for Game Dev Rustaceans 🦀

C++ Game Utility Libraries: for Game Dev Rustaceans 🦀

c++
gaming
<PREVIOUS POST
NEXT POST >
LATEST POST >>

Leave a comment …

Your information will be handled in line with our Privacy Policy .

Ask for more

1 Nov 2022 — Astro Server-Side Rendering: Edge Search Site
3 Oct 2022 — Svelte eCommerce Site: SvelteKit Snipcart Storefront
1 Sept 2022 — Get Started with SvelteKit Headless WordPress

Copyright © 2020 – 2025 Rodney Johnson. All Rights Reserved. Please read important copyright and intellectual property information.

  • Home
  • Profile
  • Plus +
  • Newsletter
  • Contact
  • Links
  • Terms of Use
  • Privacy Policy
We use cookies  to enhance visitors’ experience. Please click the “Options” button to make your choice.  Learn more here.