Skip to content

Latest commit

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

TinyJSON

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.

License: MITC++98Platform

✨ Features

  • 🎯 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.h and you're ready to go
  • 🗑️ Key Removal - Dynamically add and remove object keys
  • 🔍 Array Index Paths - Access array elements via paths: "options.0.label"

📋 Table of Contents

🚀 Quick Start

#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");

📦 Installation

Header-Only Library

Simply copy Json.h to your project and include it:

#include"Json.h"

Requirements

  • C++98 or later
  • Standard library: <string>, <vector>, <map>, <exception>, <cstdio>
  • No external dependencies

Xbox 360 Setup

// 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);

📖 Basic Usage

Creating JSON Objects

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");

Parsing JSON

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();

Serialization

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);

🛣️ Path-Based Access

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"));

Array Index Paths

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));

🛡️ Safe Access with Defaults

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 int
  • float, double
  • bool
  • std::string

💾 File I/O

Simple File Operations

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");

Verbose File Operations (with error messages)

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;
}

Xbox 360 File Paths

// 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;
}
}

🗑️ Key Removal

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");

🎮 Xbox 360 Compatibility

TinyJSON is designed to work with Xbox 360's older C++ compiler (similar to Visual C++ 2010).

❌ Avoid These (C++11 Features)

// 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

✅ Use These Instead

// 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;

Building Menu Systems (Xbox 360 Style)

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));

📚 API Reference

Construction & Types

tinyjson::json obj; // null
tinyjson::json str("text"); // string
tinyjson::json num(42); // integer
tinyjson::json flt(3.14); // float
tinyjson::json flag(true); // boolean

Type Checking

boolis_null() const;
boolis_boolean() const;
boolis_number() const;
boolis_string() const;
boolis_array() const;
boolis_object() const;

Value Access

boolget_bool() const;
longlongget_int() const;
doubleget_float() const;
const std::string& get_string() const;

Safe Access

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;

Path Operations

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);

Object Operations

json& operator[](const std::string& key);
json& at(const std::string& key);
boolcontains(const std::string& key) const;
boolerase(const std::string& key);

Array Operations

json& operator[](size_t index);
json& at(size_t index);
voidpush_back(const json& value);
size_tsize() const;
boolempty() const;

Serialization

std::string dump(int indent = -1) const;
static json parse(const std::string& str);

File I/O

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);

Iteration

iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
iterator find(const std::string& key);

💡 Examples

Game Configuration System

#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);
}

Dynamic Menu System

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));
}

Player Save System

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;
}

Network Message Serialization

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");
}
}

🔨 Building

Standard C++ Project

g++ -std=c++98 your_project.cpp -o your_project

Xbox 360 Project

  1. Add Json.h to your Xbox 360 project
  2. Include in your source files: #include "Json.h"
  3. Build normally with Xbox 360 SDK compiler

Visual Studio

Simply add Json.h to your project and include it. Works with Visual Studio 2010 and later.

📄 License

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.

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Development Setup

  1. Clone the repository
  2. Make your changes
  3. Test with Xbox 360 compatible compiler (or Visual Studio 2010)
  4. Submit a pull request

Guidelines

  • Maintain Xbox 360 compatibility (no C++11 features)
  • Keep the header-only design
  • Add tests for new features
  • Update documentation

🐛 Known Issues

  • Subdirectory paths may not work on Xbox 360 (game:\\folder\\file.json)
    • Workaround: Use root paths like game:\\file.json
  • Very large JSON files may cause memory issues on Xbox 360
    • Workaround: Use compact serialization dump(-1) and keep structures small

🙏 Acknowledgments

  • Inspired by nlohmann/json but redesigned for Xbox 360
  • Built for the xbNetwork modding project
  • Optimized for game development and embedded systems

📞 Support

  • Issues: GitHub Issues
  • Documentation: This README and code comments
  • Examples: See examples/ directory

Made with ❤️ for game modders and Xbox 360 developers

About

a header only xbox 360 compatible Json parser

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages