Skip to content

Sven-vh/JsonReflect

Repository files navigation

JsonReflect

JsonReflect

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

Quick Start

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

Custom Types

There are 2 ways to serialize an object.

Reflection

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.

Tag Invoke

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

Resolution Order

When serializing a type, JsonReflect searches in this order at compile time:

  1. User implementations - Your tag_invoke functions
  2. Reflection - Types with JSON_REFLECT macro
  3. Library implementations - Built-in JsonReflect types
  4. 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"

Dependencies

All dependencies are included in the single header file. If using separate headers (or check extern/ folder):

Contributing

Feedback, issues, and pull requests are welcome! This project is part of my university work, so everything is a learning experience.

License

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!

About

Reflection-based JSON serializer

Topics

Resources

License

Stars

Watchers

Forks

Contributors 2

  •  
  •  

Languages