Baike.dev
All toolsOnline toolsAI codingTrendingOpen sourceNewsSubmit
Log in
< Back to tools
R

reflect-cpp

> 编程语言
Open source

A C++20 library for fast serialization, deserialization and validation using reflection. Supports JSON, Avro, Boost Serialization, BSON, Cap'n Proto, CBOR, Cere

1.9K stars0 likes0 views
WebsiteGitHub

About

A C++20 library for fast serialization, deserialization and validation using reflection. Supports JSON, Avro, Boost Serialization, BSON, Cap'n Proto, CBOR, Cere

reflect-cpp

** Documentation**: https://rfl.getml.com

reflect-cpp is a C++-20/C++-26 library for fast serialization, deserialization and validation using reflection, similar to pydantic in Python, serde in Rust, encoding in Go or aeson in Haskell.

reflect-cpp supports C++-26 reflection, but most of the functionality is also available in C++-20, except where explicitly noted otherwise.

Moreover, reflect-cpp is the basis for sqlgen, a modern, type-safe ORM and SQL query generator for C++20, inspired by Python's SQLAlchemy/SQLModel and Rust's Diesel. It provides a fluent, composable interface for database operations with compile-time type checking and SQL injection protection.

reflect-cpp and sqlgen fill important gaps in C++ development. They reduce boilerplate code and increase code safety. Together, they enable reliable and efficient ETL pipelines.

Design principles for reflect-cpp include:

  • Close integration with containers from the C++ standard library
  • Close adherence to C++ idioms
  • Out-of-the-box support for JSON
  • Simple installation
  • Simple extendability to other serialization formats
  • Simple extendability to custom classes
  • Being one of the fastest serialization libraries in existence, as demonstrated by our benchmarks

Table of Contents

On this page

  • Serialization formats
  • Feature Overview
    • Simple Example
    • More Comprehensive Example
    • Tabular data
    • CLI argument parsing
    • Error messages
    • JSON schema
    • Enums
    • Algebraic data types
    • Extra fields
    • Reflective programming
    • Standard Library Integration
  • The team behind reflect-cpp
  • License

More in our documentation:

  • Installation ↗
  • C++26 reflection ↗
  • Benchmarks ↗
  • How to contribute ↗
  • Compiling and running the tests ↗

Serialization formats

reflect-cpp provides a unified reflection-based interface across different serialization formats. It is deliberately designed in a very modular way, using concepts, to make it as easy as possible to interface various C or C++ libraries related to serialization. Refer to the documentation for details.

The following table lists the serialization formats currently supported by reflect-cpp and the underlying libraries used:

Format Library Version License Remarks
JSON yyjson >= 0.8.0 MIT out-of-the-box support, included in this repository
Avro avro-c >= 1.11.3 Apache 2.0 Schemaful binary format
Boost.Serialization Boost.Serialization >= 1.74.0 BSL 1.0 Streaming binary format with archive interop
BSON libbson >= 1.25.1 Apache 2.0 JSON-like binary format
Cap'n Proto capnproto >= 1.0.2 MIT Schemaful binary format
CBOR jsoncons >= 0.176.0 BSL 1.0 JSON-like binary format
cli (none) (none) MIT Command line interface
env (none) (none) MIT Environment variables
Cereal Cereal >= 1.3.2 BSD C++ serialization library with multiple formats
CSV Apache Arrow >= 21.0.0 Apache 2.0 Tabular textual format
flexbuffers flatbuffers >= 23.5.26 Apache 2.0 Schema-less version of flatbuffers, binary format
msgpack msgpack-c >= 6.0.0 BSL 1.0 JSON-like binary format
parquet Apache Arrow >= 21.0.0 Apache 2.0 Tabular binary format
TOML toml++ >= 3.4.0 MIT Textual format with an emphasis on readability
UBJSON jsoncons >= 0.176.0 BSL 1.0 JSON-like binary format
XML pugixml >= 1.14 MIT Textual format used in many legacy projects
YAML yaml-cpp >= 0.8.0 MIT Textual format with an emphasis on readability
yas yas >= 7.1.0 BSL 1.0 Very fast and compact serialization library

Support for more serialization formats is in development. Refer to the issues for details.

Please also refer to the conanfile.py or vcpkg.json in this repository.

Feature Overview

Simple Example

cpp
#include <rfl/json.hpp>
#include <rfl.hpp>

struct Person {
  std::string first_name;
  std::string last_name;
  int age;
};

const auto homer =
    Person{.first_name = "Homer",
           .last_name = "Simpson",
           .age = 45};

// We can now write into and read from a JSON string.
const std::string json_string = rfl::json::write(homer);
auto homer2 = rfl::json::read<Person>(json_string).value();

The resulting JSON string looks like this:

json
{"first_name":"Homer","last_name":"Simpson","age":45}

You can transform the field names from snake_case to camelCase like this:

cpp
const std::string json_string =
  rfl::json::write<rfl::SnakeCaseToCamelCase>(homer);
auto homer2 =
  rfl::json::read<Person, rfl::SnakeCaseToCamelCase>(json_string).value();

The resulting JSON string looks like this:

json
{"firstName":"Homer","lastName":"Simpson","age":45}

Or you can use another format, such as YAML.

cpp
#include <rfl/yaml.hpp>

// ... (same as above)

const std::string yaml_string = rfl::yaml::write(homer);
auto homer2 = rfl::yaml::read<Person>(yaml_string).value();

The resulting YAML string looks like this:

yaml
first_name: Homer
last_name: Simpson
age: 45

This will work for just about any example in the entire documentation and any of the following formats, except where explicitly noted otherwise:

…

More Comprehensive Example

…

This results in the following JSON string:

json
{"firstName":"Homer","lastName":"Simpson","town":"Springfield","birthday":"1987-04-19","age":45,"email":"[email protected]","children":[{"firstName":"Bart","lastName":"Simpson","town":"Springfield","birthday":"1987-04-19","age":10,"email":"[email protected]","children":[]},{"firstName":"Lisa","lastName":"Simpson","town":"Springfield","birthday":"1987-04-19","age":8,"email":"[email protected]","children":[]},{"firstName":"Maggie","lastName":"Simpson","town":"Springfield","birthday":"1987-04-19","age":0,"email":"[email protected]","children":[]}]}

We can also create structs from the string:

cpp
auto homer2 = rfl::json::read<Person>(json_string).value();

// Fields can be accessed like this:
std::cout << "Hello, my name is " << homer.first_name() << " "
          << homer.last_name() << "." << std::endl;

// Since homer2 is mutable, we can also change the values like this:
homer2.first_name = "Marge";

std::cout << "Hello, my name is " << homer2.first_name() << " "
          << homer2.last_name() << "." << std::endl;

Tabular data

reflect-cpp also supports tabular data formats, like CSV or Parquet:

…

This will resulting CSV will look like this:

"first_name","last_name","town","birthday","age","email"
"Bart","Simpson","Springfield",1987-04-19,10,"[email protected]"
"Lisa","Simpson","Springfield",1987-04-19,8,"[email protected]"
"Maggie","Simpson","Springfield",1987-04-19,0,"[email protected]"
"Homer","Simpson","Springfield",1987-04-19,45,"[email protected]"

Environment variables

reflect-cpp can also read from and write to environment variables using rfl::env::read and rfl::env::write:

cpp
#include <rfl/env.hpp>

struct Config {
  std::string host;
  int port;
  bool verbose;
};

const auto config = Config{.host = "localhost", .port = 8080, .verbose = true};

rfl::env::write(config);
// Sets HOST=localhost, PORT=8080, VERBOSE=true

const auto config2 = rfl::env::read<Config>().value();

Nested structs are flattened with _ as a separator (e.g., DATABASE_HOST). Arrays use _INDEX suffix (e.g., TAGS_0, TAGS_1). Enums are serialized via their enumerator name (e.g., "green" for Color::green). All field names are converted to uppercase by default.

CLI argument parsing

reflect-cpp can also parse command-line arguments directly into structs using rfl::cli::read:

cpp
#include <rfl/cli.hpp>

struct Config {
  std::string host_name;
  int port;
  bool verbose;
  std::vector<std::string> tags;
};

int main(int argc, char* argv[]) {
  const auto config = rfl::cli::read<Config>(argc, argv).value();
  // ./app --host-name=localhost --port=8080 --verbose --tags=a,b,c
}

Field names are automatically converted from snake_case to kebab-case (host_name matches --host-name).

You can mark fields as positional arguments with rfl::Positional<T> and add single-character aliases with rfl::Short<"x", T>:

cpp
struct Config {
  rfl::Positional<std::string> input_file;
  rfl::Short<"o", std::string> output_dir;
  rfl::Short<"v", bool> verbose;
  int count;
};

// ./app data.csv -o /tmp/out -v --count=10

Nested structs, std::optional, std::vector, enums, rfl::Flatten and rfl::Rename are all supported. Refer to the documentation for details.

Error messages

reflect-cpp returns clear and comprehensive error messages:

cpp
const std::string faulty_json_string =
    R"({"firstName":"Homer","lastName":12345,"town":"Springfield","birthday":"04/19/1987","age":145,"email":"h

Issues· 0 open

View all issuesOpen on GitHub

No open issues yet, or sync has not completed.

> Tags

C++

No comments yet. Be the first to share.

> Details

PublishedAug 1, 2026
UpdatedSep 17, 2026
Category编程语言
PricingOpen source

> Related tools

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言