A lightweight, header-only JSON library optimized for Xbox 360 and legacy C++ environments. Features insertion-order preservation, path-based access, and zero C++11 dependencies.
- 🎯 Insertion Order Preservation - Keys maintain the order they were added (not alphabetically sorted)
- 🛣️ Path-Based Access - Access nested values with dot notation:
"player.stats.health" - 🛡️ Safe Access with Defaults - Never crash on missing keys with
.value()methods - 💾 File I/O Built-in - Load and save JSON files with one function call
- 🎮 Xbox 360 Compatible - No C++11 features, works with older compilers
- 📦 Header-Only - Just include
Json.hand you're ready to go - 🗑️ Key Removal - Dynamically add and remove object keys
- 🔍 Array Index Paths - Access array elements via paths:
"options.0.label"
- Quick Start
- Installation
- Basic Usage
- Path-Based Access
- Safe Access with Defaults
- File I/O
- Key Removal
- Xbox 360 Compatibility
- API Reference
- Examples
- Building
- License
#include"Json.h"// Create JSON object
tinyjson::json config;
config["username"] = "Player1";
config["level"] = 42;
config["settings"]["volume"] = 75;
// Access with pathsint volume = config.value_at_path<int>("settings.volume", 50);
// Save to file
config.save_to_file("game:\\config.json", 2);
// Load from file
tinyjson::json loaded = tinyjson::json::load_from_file("game:\\config.json");Simply copy Json.h to your project and include it:
#include"Json.h"- C++98 or later
- Standard library:
<string>,<vector>,<map>,<exception>,<cstdio> - No external dependencies
// Works directly with Xbox 360 SDK
#include"Json.h"// Use Xbox 360 file paths
tinyjson::json config;
config.save_to_file("game:\\settings.json", 2);tinyjson::json obj;
// Basic types
obj["name"] = "Dominik";
obj["age"] = 25;
obj["score"] = 12345.67;
obj["active"] = true;
obj["data"] = nullptr;
// Nested objects
obj["settings"]["theme"] = "dark";
obj["settings"]["language"] = "en";
// Arrays
obj["items"].push_back("sword");
obj["items"].push_back("shield");
obj["items"].push_back("potion");std::string json_str = R"({ "player": { "name": "Hero", "health": 100 }})";
tinyjson::json parsed = tinyjson::json::parse(json_str);
std::string name = parsed["player"]["name"].get_string();
int health = parsed["player"]["health"].get_int();tinyjson::json obj;
obj["key"] = "value";
// Pretty print with indentation
std::string pretty = obj.dump(2);
// Compact (no whitespace)
std::string compact = obj.dump(-1);Access nested values using dot notation:
tinyjson::json game;
game["player"]["stats"]["health"] = 100;
game["player"]["stats"]["mana"] = 50;
game["player"]["inventory"]["weapon"] = "Sword";
// Access with pathsint health = game.at_path("player.stats.health").get_int();
std::string weapon = game.at_path("player.inventory.weapon").get_string();
// Check if path existsif (game.has_path("player.stats.stamina")) {
// Path exists
}
// Set values via path (creates intermediate objects)
game.set_path("player.stats.stamina", tinyjson::json(75));
game.set_path("settings.graphics.quality", tinyjson::json("Ultra"));tinyjson::json menu;
menu["options"][0]["label"] = "God Mode";
menu["options"][0]["enabled"] = false;
menu["options"][1]["label"] = "Infinite Ammo";
menu["options"][1]["enabled"] = true;
// Access array elements via paths
std::string label = menu.at_path("options.0.label").get_string();
bool enabled = menu.at_path("options.1.enabled").get_bool();
// Modify array elements
menu.set_path("options.0.enabled", tinyjson::json(true));Never crash on missing keys:
tinyjson::json config;
config["graphics"]["quality"] = "High";
config["audio"]["volume"] = 75;
// Safe access - returns default if key doesn't existint fps = config.value<int>("fps", 60); // Missing key → 60
std::string quality = config["graphics"].value<std::string>("quality", "Low"); // "High"bool vsync = config["graphics"].value<bool>("vsync", true); // Missing → true// Path-based safe accessint lives = config.value_at_path<int>("game.lives", 3);
std::string weapon = config.value_at_path<std::string>("player.weapon", "Default");Supported Types:
int,long long,unsigned intfloat,doubleboolstd::string
tinyjson::json config;
config["setting1"] = "value1";
config["setting2"] = 42;
// Save to filebool success = config.save_to_file("config.json", 2);
// Load from file
tinyjson::json loaded = tinyjson::json::load_from_file("config.json");std::string error_msg;
// Save with error detailsif (!config.save_to_file_verbose("config.json", 2, error_msg)) {
std::cout << "Save failed: " << error_msg << std::endl;
}
// Load with error detailstry {
tinyjson::json loaded = tinyjson::json::load_from_file_verbose("config.json", error_msg);
} catch (const tinyjson::parse_error& e) {
std::cout << "Load failed: " << error_msg << std::endl;
}// Try different path formats
std::vector<std::string> paths;
paths.push_back("game:\\config.json"); // Game partition (usually works)
paths.push_back("hdd:\\config.json"); // Hard drive
paths.push_back("D:\\config.json"); // Alternativefor (size_t i = 0; i < paths.size(); i++) {
if (config.save_to_file(paths[i], 2)) {
// Success!break;
}
}tinyjson::json user;
user["username"] = "player1";
user["password"] = "secret123";
user["email"] = "player@example.com";
// Remove sensitive databool removed = user.erase("password"); // Returns true if key existed// Remove multiple keys
user.erase("session_token");
user.erase("api_key");TinyJSON is designed to work with Xbox 360's older C++ compiler (similar to Visual C++ 2010).
// DON'T USE - Won't compile on Xbox 360
std::vector<std::string> items = {"item1", "item2", "item3"}; // Initializer listsfor (constauto& item : items) { } // Range-based for
std::string s = std::to_string(123); // std::to_string// DO THIS - Xbox 360 compatible
std::vector<std::string> items;
items.push_back("item1");
items.push_back("item2");
items.push_back("item3");
// Iteration method 1: Traditional for loopfor (size_t i = 0; i < items.size(); i++) {
std::string item = items[i];
}
// Iteration method 2: for each (Microsoft extension)foreach (const std::string& item in items) {
// use item
}
// Number to string conversionchar buffer[64];
sprintf(buffer, "%d", 123);
std::string s = buffer;tinyjson::json menu;
menu["title"] = "xbNetwork Menu";
// Add options individually
tinyjson::json opt1;
opt1["id"] = "god_mode";
opt1["label"] = "God Mode";
opt1["enabled"] = false;
opt1["hotkey"] = "DPAD_UP";
menu["options"].push_back(opt1);
tinyjson::json opt2;
opt2["id"] = "infinite_ammo";
opt2["label"] = "Infinite Ammo";
opt2["enabled"] = false;
opt2["hotkey"] = "DPAD_DOWN";
menu["options"].push_back(opt2);
// Access with defaults
std::string title = menu.value<std::string>("title", "Default Menu");
bool enabled = menu.value_at_path<bool>("options.0.enabled", false);
// Modify via path
menu.set_path("options.0.enabled", tinyjson::json(true));tinyjson::json obj; // null
tinyjson::json str("text"); // string
tinyjson::json num(42); // integer
tinyjson::json flt(3.14); // float
tinyjson::json flag(true); // booleanboolis_null() const;
boolis_boolean() const;
boolis_number() const;
boolis_string() const;
boolis_array() const;
boolis_object() const;boolget_bool() const;
longlongget_int() const;
doubleget_float() const;
const std::string& get_string() const;template<typename T>
T value(const std::string& key, const T& default_val) const;
template<typename T>
T value_at_path(const std::string& path, const T& default_val) const;json& at_path(const std::string& path);
const json& at_path(const std::string& path) const;
boolhas_path(const std::string& path) const;
voidset_path(const std::string& path, const json& value);json& operator[](const std::string& key);
json& at(const std::string& key);
boolcontains(const std::string& key) const;
boolerase(const std::string& key);json& operator[](size_t index);
json& at(size_t index);
voidpush_back(const json& value);
size_tsize() const;
boolempty() const;std::string dump(int indent = -1) const;
static json parse(const std::string& str);boolsave_to_file(const std::string& filepath, int indent = 2) const;
boolsave_to_file_verbose(const std::string& filepath, int indent, std::string& error_msg) const;
static json load_from_file(const std::string& filepath);
static json load_from_file_verbose(const std::string& filepath, std::string& error_msg);iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
iterator find(const std::string& key);#include"Json.h"voidload_game_config() {
tinyjson::json config;
try {
config = tinyjson::json::load_from_file("game:\\config.json");
} catch (...) {
// Use defaults if file doesn't exist
config["graphics"]["quality"] = "Medium";
config["audio"]["volume"] = 50;
}
// Safe access with defaults
std::string quality = config.value_at_path<std::string>("graphics.quality", "Low");
int volume = config.value_at_path<int>("audio.volume", 50);
bool vsync = config.value_at_path<bool>("graphics.vsync", true);
apply_settings(quality, volume, vsync);
}tinyjson::json create_menu() {
tinyjson::json menu;
menu["title"] = "Mod Menu";
menu["selected_index"] = 0;
// Add menu itemsconstchar* labels[] = {"God Mode", "Infinite Ammo", "Super Speed", "Teleport"};
constchar* hotkeys[] = {"F1", "F2", "F3", "F4"};
for (int i = 0; i < 4; i++) {
tinyjson::json item;
item["label"] = labels[i];
item["hotkey"] = hotkeys[i];
item["enabled"] = false;
menu["items"].push_back(item);
}
return menu;
}
voidtoggle_menu_item(tinyjson::json& menu, int index) {
// Build pathchar path[64];
sprintf(path, "items.%d.enabled", index);
// Get current valuebool current = menu.value_at_path<bool>(path, false);
// Toggle
menu.set_path(path, tinyjson::json(!current));
}voidsave_player_data(const PlayerData& player) {
tinyjson::json save;
// Basic info
save["name"] = player.name;
save["level"] = player.level;
save["xp"] = player.experience;
// Stats
save["stats"]["health"] = player.maxHealth;
save["stats"]["mana"] = player.maxMana;
save["stats"]["strength"] = player.strength;
// Inventoryfor (size_t i = 0; i < player.inventory.size(); i++) {
tinyjson::json item;
item["id"] = player.inventory[i].id;
item["quantity"] = player.inventory[i].quantity;
save["inventory"].push_back(item);
}
// Save to file
save.save_to_file("game:\\save_data.json", 2);
}
PlayerData load_player_data() {
PlayerData player;
try {
tinyjson::json save = tinyjson::json::load_from_file("game:\\save_data.json");
player.name = save.value<std::string>("name", "Player");
player.level = save.value<int>("level", 1);
player.experience = save.value<int>("xp", 0);
player.maxHealth = save.value_at_path<int>("stats.health", 100);
player.maxMana = save.value_at_path<int>("stats.mana", 50);
player.strength = save.value_at_path<int>("stats.strength", 10);
// Load inventory...
} catch (...) {
// Return default player if load fails
}
return player;
}std::string create_network_message(const std::string& type, const std::string& data) {
tinyjson::json msg;
msg["type"] = type;
msg["timestamp"] = get_current_time();
msg["data"] = data;
// Compact format for networkreturn msg.dump(-1);
}
voidparse_network_message(const std::string& json_str) {
try {
tinyjson::json msg = tinyjson::json::parse(json_str);
std::string type = msg.value<std::string>("type", "unknown");
std::string data = msg.value<std::string>("data", "");
handle_message(type, data);
} catch (const tinyjson::parse_error& e) {
log_error("Invalid message format");
}
}g++ -std=c++98 your_project.cpp -o your_project- Add
Json.hto your Xbox 360 project - Include in your source files:
#include "Json.h" - Build normally with Xbox 360 SDK compiler
Simply add Json.h to your project and include it. Works with Visual Studio 2010 and later.
MIT License
Copyright (c) 2025
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Contributions are welcome! Please feel free to submit a Pull Request.
- Clone the repository
- Make your changes
- Test with Xbox 360 compatible compiler (or Visual Studio 2010)
- Submit a pull request
- Maintain Xbox 360 compatibility (no C++11 features)
- Keep the header-only design
- Add tests for new features
- Update documentation
- Subdirectory paths may not work on Xbox 360 (
game:\\folder\\file.json)- Workaround: Use root paths like
game:\\file.json
- Workaround: Use root paths like
- Very large JSON files may cause memory issues on Xbox 360
- Workaround: Use compact serialization
dump(-1)and keep structures small
- Workaround: Use compact serialization
- Inspired by nlohmann/json but redesigned for Xbox 360
- Built for the xbNetwork modding project
- Optimized for game development and embedded systems
- Issues: GitHub Issues
- Documentation: This README and code comments
- Examples: See
examples/directory
Made with ❤️ for game modders and Xbox 360 developers