Header-only reflection-based JSON serializer.
Automatically serializes and deserializes any C++ object to and from JSON.
struct GameSettings {
int volume = 50;
float sensitivity = 1.0f;
bool fullscreen = true;
Difficulty difficulty = Difficulty::Medium;
};
JSON_REFLECT(GameSettings, volume, sensitivity, fullscreen, difficulty);
GameSettings input{};
json j = JsonReflect::to_json(input);Output:
{
"volume": 75,
"sensitivity": 1.0,
"fullscreen": false,
"difficulty": "Medium"
}1. Installation
Option A: Single Header (Recommended)
Download single_header/JsonReflect.hpp - includes everything in one file.
#include "JsonReflect.hpp"Option B: Separate Headers
Download all headers from the root directory + the extern/ folder, then:
#include "JsonReflect.hpp"2. Reflect Your Struct/Class
struct GameSettings {
int volume = 50;
float sensitivity = 1.0f;
bool fullscreen = true;
Difficulty difficulty = Difficulty::Medium;
};
JSON_REFLECT(GameSettings, volume, sensitivity, fullscreen, difficulty);3. Serialize
GameSettings input;
input.volume = 75;
input.sensitivity = 1.5f;
input.fullscreen = false;
input.difficulty = Difficulty::Hard;
JsonReflect::json serialized = JsonReflect::to_json(input);
std::ofstream("settings.json") << serialized.dump();4. Deserialize
JsonReflect::json parsed_json = JsonReflect::json::parse(std::ifstream("settings.json"));
GameSettings output{};
JsonReflect::from_json(parsed_json, output);
assert(output.volume == 75);
assert(output.sensitivity == 1.5f);
assert(output.fullscreen == false);
assert(output.difficulty = Difficulty::Hard);There are 2 ways to serialize an object.
struct GameSettings {
int volume = 50;
float sensitivity = 1.0f;
bool fullscreen = true;
Difficulty difficulty = Difficulty::Medium;
};
JSON_REFLECT(GameSettings, volume, sensitivity, fullscreen, difficulty);Tip
Use the BEFRIEND_JSON_REFLECT() macro to let JsonReflect access private variables.
If the macro is not sufficient, you can implement a tag invoke function that will be called when JsonReflect encounters that object.
struct CustomObject {
int id = 0;
std::string name;
float value = 0.0f;
void init();
};
inline JsonReflect::json tag_invoke(JsonReflect::serialize_t, const CustomObject& object) {
JsonReflect::json j;
j["id"] = JsonReflect::to_json(object.id);
j["name"] = JsonReflect::to_json(object.name);
j["value"] = JsonReflect::to_json(object.value);
return j;
}
inline void tag_invoke(JsonReflect::deserialize_t, const JsonReflect::json& j, CustomObject& object) {
if (j.contains("id")) JsonReflect::from_json(j["id"], object.id);
if (j.contains("name")) JsonReflect::from_json(j["name"], object.name);
if (j.contains("value")) JsonReflect::from_json(j["value"], object.value);
// Call init after deserialization
object.init();
}Or, still use the reflection, but also do something custom:
struct CustomObject {
int id = 0;
std::string name;
float value = 0.0f;
void init() {};
};
JSON_REFLECT(CustomObject, id, name, value);
inline void tag_invoke(JsonReflect::deserialize_t, const JsonReflect::json& j, CustomObject& object) {
// Use default visitable deserialization
JsonReflect::Detail::from_json_visitable(j, object);
// Call init after deserialization
object.init();
}When serializing a type, JsonReflect searches in this order at compile time:
- User implementations - Your tag_invoke functions
- Reflection - Types with
JSON_REFLECTmacro - Library implementations - Built-in JsonReflect types
- nlohmann::json - Types supported by nlohmann
This means you can always override library and reflection behavior with your own tag_invoke implementations.
If no implementation is found:
"JsonSerializer Error: No suitable serialize implementation found for type T"
All dependencies are included in the single header file. If using separate headers (or check extern/ folder):
- nlohmann::json - JSON parsing and serialization
- visit_struct - Compile-time struct reflection
- magic_enum - Enum reflection
- C++17 or later
Feedback, issues, and pull requests are welcome! This project is part of my university work, so everything is a learning experience.
MIT License - See LICENSE
As a student, credit or a quick note about what you're using it for is greatly appreciated! It motivates me to keep contributing to open source!