{"id":13521187,"url":"https://github.com/getml/reflect-cpp","last_synced_at":"2025-12-29T22:05:39.715Z","repository":{"id":197491077,"uuid":"697358974","full_name":"getml/reflect-cpp","owner":"getml","description":"A C++20 library for fast serialization, deserialization and validation using reflection. Supports JSON, BSON, CBOR, flexbuffers, msgpack, TOML, XML, YAML / msgpack.org[C++20]","archived":false,"fork":false,"pushed_at":"2024-10-29T19:24:37.000Z","size":4212,"stargazers_count":1060,"open_issues_count":40,"forks_count":92,"subscribers_count":23,"default_branch":"main","last_synced_at":"2024-10-29T20:44:49.680Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://getml.github.io/reflect-cpp/","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/getml.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":"docs/supporting_your_own_format.md","governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-09-27T15:08:58.000Z","updated_at":"2024-10-29T20:08:49.000Z","dependencies_parsed_at":"2024-01-13T17:09:51.664Z","dependency_job_id":"313e9ca8-664a-4332-9cab-c6e18d356bf4","html_url":"https://github.com/getml/reflect-cpp","commit_stats":null,"previous_names":["getml/reflect-cpp"],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/getml%2Freflect-cpp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/getml%2Freflect-cpp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/getml%2Freflect-cpp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/getml%2Freflect-cpp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/getml","download_url":"https://codeload.github.com/getml/reflect-cpp/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246535786,"owners_count":20793322,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T06:00:30.270Z","updated_at":"2025-12-29T22:05:39.709Z","avatar_url":"https://github.com/getml.png","language":"C++","readme":"# ![C++](https://img.shields.io/badge/c++-%2300599C.svg?style=for-the-badge\u0026logo=c%2B%2B\u0026logoColor=white) reflect-cpp\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://github.com/getml/reflect-cpp/graphs/commit-activity)\n[![Generic badge](https://img.shields.io/badge/C++-20-blue.svg)](https://shields.io/)\n[![Generic badge](https://img.shields.io/badge/gcc-11+-blue.svg)](https://shields.io/)\n[![Generic badge](https://img.shields.io/badge/clang-14+-blue.svg)](https://shields.io/)\n[![Generic badge](https://img.shields.io/badge/MSVC-17+-blue.svg)](https://shields.io/)\n[![Conan Center](https://img.shields.io/conan/v/reflect-cpp)](https://conan.io/center/recipes/reflect-cpp)\n\n**📖 Documentation**: https://rfl.getml.com\n\n![image](banner1.png)\n\n**reflect-cpp** is a C++-20 library for **fast serialization, deserialization and validation** using reflection, similar to [pydantic](https://github.com/pydantic/pydantic) in Python, [serde](https://github.com/serde-rs) in Rust, [encoding](https://github.com/golang/go/tree/master/src/encoding) in Go or [aeson](https://github.com/haskell/aeson/tree/master) in Haskell.\n\nMoreover, reflect-cpp is the basis for [sqlgen](https://github.com/getml/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. \n\nreflect-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.\n\n### Design principles for reflect-cpp include:\n\n- Close integration with [containers](https://github.com/getml/reflect-cpp?tab=readme-ov-file#support-for-containers) from the C++ standard library\n- Close adherence to C++ idioms\n- Out-of-the-box support for [JSON](https://rfl.getml.com/supported_formats/json)\n- Simple [installation](https://rfl.getml.com/install)\n- Simple extendability to [other serialization formats](https://rfl.getml.com/supported_formats/supporting_your_own_format)\n- Simple extendability to [custom classes](https://rfl.getml.com/concepts/custom_classes)\n- Being one of the fastest serialization libraries in existence, as demonstrated by our [benchmarks](https://rfl.getml.com/benchmarks)\n\n\u003cbr\u003e\n\n## Table of Contents\n\n### On this page\n  - [Serialization formats](#serialization-formats)\n  - [Feature Overview](#feature-overview)\n    - [Simple Example](#simple-example)\n    - [More Comprehensive Example](#more-comprehensive-example)\n    - [Tabular data](#tabular-data)\n    - [Error messages](#error-messages)\n    - [JSON schema](#json-schema)\n    - [Enums](#enums)\n    - [Algebraic data types](#algebraic-data-types)\n    - [Extra fields](#extra-fields)\n    - [Reflective programming](#reflective-programming)\n    - [Standard Library Integration](#support-for-containers) \n  - [The team behind reflect-cpp](#the-team-behind-reflect-cpp)\n  - [License](#license)\n\n### More in our [documentation](https://rfl.getml.com):\n  - [Installation ↗](https://rfl.getml.com/install/#option-2-compilation-using-cmake)\n  - [Benchmarks ↗](https://rfl.getml.com/benchmarks)\n  - [How to contribute ↗](https://rfl.getml.com/contributing) \n  - [Compiling and running the tests ↗](https://rfl.getml.com/contributing/#compiling-and-running-the-tests)\n\n\n## Serialization formats\n\nreflect-cpp provides a unified reflection-based interface across different serialization formats. It is deliberately designed in a very modular way, using [concepts](https://en.cppreference.com/w/cpp/language/constraints), to make it as easy as possible to interface various C or C++ libraries related to serialization. Refer to the [documentation](https://rfl.getml.com/supported_formats/bson/) for details.\n\nThe following table lists the serialization formats currently supported by reflect-cpp and the underlying libraries used:\n\n| Format       | Library                                              | Version      | License    | Remarks                                              |\n|--------------|------------------------------------------------------|--------------|------------| -----------------------------------------------------|\n| JSON         | [yyjson](https://github.com/ibireme/yyjson)          | \u003e= 0.8.0     | MIT        | out-of-the-box support, included in this repository  |\n| Avro         | [avro-c](https://avro.apache.org/docs/1.11.1/api/c/) | \u003e= 1.11.3    | Apache 2.0 | Schemaful binary format                              |\n| BSON         | [libbson](https://github.com/mongodb/mongo-c-driver) | \u003e= 1.25.1    | Apache 2.0 | JSON-like binary format                              |\n| Cap'n Proto  | [capnproto](https://capnproto.org)                   | \u003e= 1.0.2     | MIT        | Schemaful binary format                              |\n| CBOR         | [jsoncons](https://github.com/danielaparker/jsoncons)| \u003e= 0.176.0   | BSL 1.0    | JSON-like binary format                              |\n| CSV          | [Apache Arrow](https://arrow.apache.org/)            | \u003e= 21.0.0    | Apache 2.0 | Tabular textual format                               |\n| flexbuffers  | [flatbuffers](https://github.com/google/flatbuffers) | \u003e= 23.5.26   | Apache 2.0 | Schema-less version of flatbuffers, binary format    |\n| msgpack      | [msgpack-c](https://github.com/msgpack/msgpack-c)    | \u003e= 6.0.0     | BSL 1.0    | JSON-like binary format                              |\n| parquet      | [Apache Arrow](https://arrow.apache.org/)            | \u003e= 21.0.0    | Apache 2.0 | Tabular binary format                                |\n| TOML         | [toml++](https://github.com/marzer/tomlplusplus)     | \u003e= 3.4.0     | MIT        | Textual format with an emphasis on readability       |\n| UBJSON       | [jsoncons](https://github.com/danielaparker/jsoncons)| \u003e= 0.176.0   | BSL 1.0    | JSON-like binary format                              |\n| XML          | [pugixml](https://github.com/zeux/pugixml)           | \u003e= 1.14      | MIT        | Textual format used in many legacy projects          |\n| YAML         | [yaml-cpp](https://github.com/jbeder/yaml-cpp)       | \u003e= 0.8.0     | MIT        | Textual format with an emphasis on readability       |\n\nSupport for more serialization formats is in development. Refer to the [issues](https://github.com/getml/reflect-cpp/issues) for details.\n\nPlease also refer to the *conanfile.py* or *vcpkg.json* in this repository.\n\n\n## Feature Overview\n\n### Simple Example\n\n```cpp\n#include \u003crfl/json.hpp\u003e\n#include \u003crfl.hpp\u003e\n\nstruct Person {\n  std::string first_name;\n  std::string last_name;\n  int age;\n};\n\nconst auto homer =\n    Person{.first_name = \"Homer\",\n           .last_name = \"Simpson\",\n           .age = 45};\n\n// We can now write into and read from a JSON string.\nconst std::string json_string = rfl::json::write(homer);\nauto homer2 = rfl::json::read\u003cPerson\u003e(json_string).value();\n```\n\nThe resulting JSON string looks like this:\n\n```json\n{\"first_name\":\"Homer\",\"last_name\":\"Simpson\",\"age\":45}\n```\n\nYou can transform the field names from `snake_case` to `camelCase` like this:\n\n```cpp\nconst std::string json_string = \n  rfl::json::write\u003crfl::SnakeCaseToCamelCase\u003e(homer);\nauto homer2 = \n  rfl::json::read\u003cPerson, rfl::SnakeCaseToCamelCase\u003e(json_string).value();\n```\n\nThe resulting JSON string looks like this:\n\n```json\n{\"firstName\":\"Homer\",\"lastName\":\"Simpson\",\"age\":45}\n```\n\nOr you can use another format, such as YAML.\n\n```cpp\n#include \u003crfl/yaml.hpp\u003e\n\n// ... (same as above)\n\nconst std::string yaml_string = rfl::yaml::write(homer);\nauto homer2 = rfl::yaml::read\u003cPerson\u003e(yaml_string).value();\n```\n\nThe resulting YAML string looks like this:\n\n```yaml\nfirst_name: Homer\nlast_name: Simpson\nage: 45\n```\n\nThis will work for just about any example in the entire documentation \nand any of the following formats, except where explicitly noted otherwise:\n\n```cpp\nrfl::avro::write(homer);\nrfl::bson::write(homer);\nrfl::capnproto::write(homer);\nrfl::cbor::write(homer);\nrfl::flexbuf::write(homer);\nrfl::msgpack::write(homer);\nrfl::toml::write(homer);\nrfl::ubjson::write(homer);\nrfl::xml::write(homer);\n\nrfl::avro::read\u003cPerson\u003e(avro_bytes);\nrfl::bson::read\u003cPerson\u003e(bson_bytes);\nrfl::capnproto::read\u003cPerson\u003e(capnproto_bytes);\nrfl::cbor::read\u003cPerson\u003e(cbor_bytes);\nrfl::flexbuf::read\u003cPerson\u003e(flexbuf_bytes);\nrfl::msgpack::read\u003cPerson\u003e(msgpack_bytes);\nrfl::toml::read\u003cPerson\u003e(toml_string);\nrfl::ubjson::read\u003cPerson\u003e(ubjson_bytes);\nrfl::xml::read\u003cPerson\u003e(xml_string);\n```\n\n### More Comprehensive Example\n\n```cpp\n#include \u003ciostream\u003e\n#include \u003crfl/json.hpp\u003e\n#include \u003crfl.hpp\u003e\n\n// Age must be a plausible number, between 0 and 130. This will\n// be validated automatically.\nusing Age = rfl::Validator\u003cint, rfl::Minimum\u003c0\u003e, rfl::Maximum\u003c130\u003e\u003e;\n\nstruct Person {\n  rfl::Rename\u003c\"firstName\", std::string\u003e first_name;\n  rfl::Rename\u003c\"lastName\", std::string\u003e last_name = \"Simpson\";\n  std::string town = \"Springfield\";\n  rfl::Timestamp\u003c\"%Y-%m-%d\"\u003e birthday;\n  Age age;\n  rfl::Email email;\n  std::vector\u003cPerson\u003e children;\n};\n\nconst auto bart = Person{.first_name = \"Bart\",\n                         .birthday = \"1987-04-19\",\n                         .age = 10,\n                         .email = \"bart@simpson.com\"};\n\nconst auto lisa = Person{.first_name = \"Lisa\",\n                         .birthday = \"1987-04-19\",\n                         .age = 8,\n                         .email = \"lisa@simpson.com\"};\n\nconst auto maggie = Person{.first_name = \"Maggie\",\n                           .birthday = \"1987-04-19\",\n                           .age = 0,\n                           .email = \"maggie@simpson.com\"};\n\nconst auto homer =\n    Person{.first_name = \"Homer\",\n           .birthday = \"1987-04-19\",\n           .age = 45,\n           .email = \"homer@simpson.com\",\n           .children = std::vector\u003cPerson\u003e({bart, lisa, maggie})};\n\n// We can now transform this into a JSON string.\nconst std::string json_string = rfl::json::write(homer);\nstd::cout \u003c\u003c json_string \u003c\u003c std::endl;\n\n// We can also directly write into std::cout (or any other std::ostream).\nrfl::json::write(homer, std::cout) \u003c\u003c std::endl;\n```\n\nThis results in the following JSON string:\n\n```json\n{\"firstName\":\"Homer\",\"lastName\":\"Simpson\",\"town\":\"Springfield\",\"birthday\":\"1987-04-19\",\"age\":45,\"email\":\"homer@simpson.com\",\"children\":[{\"firstName\":\"Bart\",\"lastName\":\"Simpson\",\"town\":\"Springfield\",\"birthday\":\"1987-04-19\",\"age\":10,\"email\":\"bart@simpson.com\",\"children\":[]},{\"firstName\":\"Lisa\",\"lastName\":\"Simpson\",\"town\":\"Springfield\",\"birthday\":\"1987-04-19\",\"age\":8,\"email\":\"lisa@simpson.com\",\"children\":[]},{\"firstName\":\"Maggie\",\"lastName\":\"Simpson\",\"town\":\"Springfield\",\"birthday\":\"1987-04-19\",\"age\":0,\"email\":\"maggie@simpson.com\",\"children\":[]}]}\n```\n\nWe can also create structs from the string:\n\n```cpp\nauto homer2 = rfl::json::read\u003cPerson\u003e(json_string).value();\n\n// Fields can be accessed like this:\nstd::cout \u003c\u003c \"Hello, my name is \" \u003c\u003c homer.first_name() \u003c\u003c \" \"\n          \u003c\u003c homer.last_name() \u003c\u003c \".\" \u003c\u003c std::endl;\n\n// Since homer2 is mutable, we can also change the values like this:\nhomer2.first_name = \"Marge\";\n\nstd::cout \u003c\u003c \"Hello, my name is \" \u003c\u003c homer2.first_name() \u003c\u003c \" \"\n          \u003c\u003c homer2.last_name() \u003c\u003c \".\" \u003c\u003c std::endl;\n```\n\n### Tabular data\n\nreflect-cpp also supports tabular data formats, like CSV or Parquet:\n\n```cpp\n#include \u003crfl/csv.hpp\u003e\n#include \u003crfl/parquet.hpp\u003e\n\nstruct Person {\n    std::string first_name;\n    std::string last_name = \"Simpson\";\n    std::string town = \"Springfield\";\n    int age;\n    rfl::Email email;\n};\n\nconst auto people =\n  std::vector\u003cPerson\u003e({Person{.first_name = \"Bart\",\n                              .birthday = \"1987-04-19\",\n                              .age = 10,\n                              .email = \"bart@simpson.com\"},\n                       Person{.first_name = \"Lisa\",\n                              .birthday = \"1987-04-19\",\n                              .age = 8,\n                              .email = \"lisa@simpson.com\"},\n                       Person{.first_name = \"Maggie\",\n                              .birthday = \"1987-04-19\",\n                              .age = 0,\n                              .email = \"maggie@simpson.com\"},\n                       Person{.first_name = \"Homer\",\n                              .birthday = \"1987-04-19\",\n                              .age = 45,\n                              .email = \"homer@simpson.com\"}});\n\nconst auto csv_string = rfl::csv::write(people);\nconst auto bytestring = rfl::parquet::write(people);\n```\n\nThis will resulting CSV will look like this:\n\n```\n\"first_name\",\"last_name\",\"town\",\"birthday\",\"age\",\"email\"\n\"Bart\",\"Simpson\",\"Springfield\",1987-04-19,10,\"bart@simpson.com\"\n\"Lisa\",\"Simpson\",\"Springfield\",1987-04-19,8,\"lisa@simpson.com\"\n\"Maggie\",\"Simpson\",\"Springfield\",1987-04-19,0,\"maggie@simpson.com\"\n\"Homer\",\"Simpson\",\"Springfield\",1987-04-19,45,\"homer@simpson.com\"\n```\n\n### Error messages\n\nreflect-cpp returns clear and comprehensive error messages:\n\n```cpp\nconst std::string faulty_json_string =\n    R\"({\"firstName\":\"Homer\",\"lastName\":12345,\"town\":\"Springfield\",\"birthday\":\"04/19/1987\",\"age\":145,\"email\":\"homer(at)simpson.com\"})\";\nconst auto result = rfl::json::read\u003cPerson\u003e(faulty_json_string);\n```\n\nYields the following error message:\n\n```\nFound 5 errors:\n1) Failed to parse field 'lastName': Could not cast to string.\n2) Failed to parse field 'birthday': String '04/19/1987' did not match format '%Y-%m-%d'.\n3) Failed to parse field 'age': Value expected to be less than or equal to 130, but got 145.\n4) Failed to parse field 'email': String 'homer(at)simpson.com' did not match format 'Email': '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$'.\n5) Field named 'children' not found.\n```\n\n### JSON schema\n\nreflect-cpp also supports generating JSON schemata:\n\n```cpp\nstruct Person {\n  std::string first_name;\n  std::string last_name;\n  rfl::Description\u003c\"Must be a proper email in the form xxx@xxx.xxx.\",\n                   rfl::Email\u003e\n      email;\n  rfl::Description\u003c\n      \"The person's children. Pass an empty array for no children.\",\n      std::vector\u003cPerson\u003e\u003e\n      children;\n  float salary;\n};\n\nconst std::string json_schema = rfl::json::to_schema\u003cPerson\u003e();\n```\n\nThe resulting JSON schema looks like this:\n\n```json\n{\"$schema\":\"https://json-schema.org/draft/2020-12/schema\",\"$ref\":\"#/$defs/Person\",\"$defs\":{\"Person\":{\"type\":\"object\",\"properties\":{\"children\":{\"type\":\"array\",\"description\":\"The person's children. Pass an empty array for no children.\",\"items\":{\"$ref\":\"#/$defs/Person\"}},\"email\":{\"type\":\"string\",\"description\":\"Must be a proper email in the form xxx@xxx.xxx.\",\"pattern\":\"^[a-zA-Z0-9._%+\\\\-]+@[a-zA-Z0-9.\\\\-]+\\\\.[a-zA-Z]{2,}$\"},\"first_name\":{\"type\":\"string\"},\"last_name\":{\"type\":\"string\"},\"salary\":{\"type\":\"number\"}},\"required\":[\"children\",\"email\",\"first_name\",\"last_name\",\"salary\"]}}}\n```\n\nNote that this is currently supported for JSON only, since most other formats do not support schemata in the first place.\n\n### Enums\n\nreflect-cpp supports scoped enumerations:\n\n```cpp\nenum class Shape { circle, square, rectangle };\n\nenum class Color { red = 256, green = 512, blue = 1024, yellow = 2048 };\n\nstruct Item {\n  float pos_x;\n  float pos_y;\n  Shape shape;\n  Color color;\n};\n\nconst auto item = Item{.pos_x = 2.0,  \n                       .pos_y = 3.0,\n                       .shape = Shape::square,\n                       .color = Color::red | Color::blue};\n\nrfl::json::write(item);\n```\n\nThis results in the following JSON string:\n\n```json\n{\"pos_x\":2.0,\"pos_y\":3.0,\"shape\":\"square\",\"color\":\"red|blue\"}\n```\n\nYou can also directly convert between enumerator values and strings with `rfl::enum_to_string()` and `rfl::string_to_enum()`, or\nobtain list of enumerator name and value pairs with `rfl::get_enumerators\u003cEnumType\u003e()` or `rfl::get_enumerator_array\u003cEnumType\u003e()`.\n\n### Algebraic data types\n\nreflect-cpp supports Pydantic-style tagged unions, which allow you to form algebraic data types:\n\n```cpp\nstruct Circle {\n    double radius;\n};\n\nstruct Rectangle {\n    double height;\n    double width;\n};\n\nstruct Square {\n    double width;\n};\n\nusing Shapes = rfl::TaggedUnion\u003c\"shape\", Circle, Square, Rectangle\u003e;\n\nconst Shapes r = Rectangle{.height = 10, .width = 5};\n\nconst auto json_string = rfl::json::write(r);\n```\n\nThis results in the following JSON string:\n\n```json\n{\"shape\":\"Rectangle\",\"height\":10.0,\"width\":5.0}\n```\n\nOther forms of tagging are supported as well. Refer to the [documentation](https://rfl.getml.com/docs-readme) for details.\n\n### Extra fields\n\nIf you don't know all of your fields at compile time, no problem. Just use `rfl::ExtraFields`:\n\n```cpp\nstruct Person {\n  std::string first_name;\n  std::string last_name = \"Simpson\";\n  rfl::ExtraFields\u003crfl::Generic\u003e extra_fields;\n};\n\nauto homer = Person{.first_name = \"Homer\"};\n\nhomer.extra_fields[\"age\"] = 45;\nhomer.extra_fields[\"email\"] = \"homer@simpson.com\";\nhomer.extra_fields[\"town\"] = \"Springfield\";\n```\n\nThis results in the following JSON string:\n\n```json\n{\"firstName\":\"Homer\",\"lastName\":\"Simpson\",\"age\":45,\"email\":\"homer@simpson.com\",\"town\":\"Springfield\"}\n```\n\n### Reflective programming\n\nBeyond serialization and deserialization, reflect-cpp also supports reflective programming in general.\n\nFor instance:\n\n```cpp\nstruct Person {\n  std::string first_name;\n  std::string last_name = \"Simpson\";\n  std::string town = \"Springfield\";\n  unsigned int age;\n  std::vector\u003cPerson\u003e children;\n};\n\nfor (const auto\u0026 f : rfl::fields\u003cPerson\u003e()) {\n  std::cout \u003c\u003c \"name: \" \u003c\u003c f.name() \u003c\u003c \", type: \" \u003c\u003c f.type() \u003c\u003c std::endl;\n}\n```\n\nYou can also create a view and then access these fields using `std::get` or `rfl::get`, or iterate over the fields at compile-time:\n\n```cpp\nauto lisa = Person{.first_name = \"Lisa\", .last_name = \"Simpson\", .age = 8};\n\nconst auto view = rfl::to_view(lisa);\n\n// view.values() is a std::tuple containing\n// pointers to the original fields.\n// This will modify the struct `lisa`:\n*std::get\u003c0\u003e(view.values()) = \"Maggie\";\n\n// All of this is supported as well:\n*view.get\u003c1\u003e() = \"Simpson\";\n*view.get\u003c\"age\"\u003e() = 0;\n*rfl::get\u003c0\u003e(view) = \"Maggie\";\n*rfl::get\u003c\"first_name\"\u003e(view) = \"Maggie\";\n\nview.apply([](const auto\u0026 f) {\n  // f is an rfl::Field pointing to the original field.\n  std::cout \u003c\u003c f.name() \u003c\u003c \": \" \u003c\u003c rfl::json::write(*f.value()) \u003c\u003c std::endl;\n});\n```\n\nIt also possible to replace fields:\n\n```cpp\nstruct Person {\n  std::string first_name;\n  std::string last_name;\n  std::vector\u003cPerson\u003e children;\n};\n\nconst auto lisa = Person{.first_name = \"Lisa\", .last_name = \"Simpson\"};\n\n// Returns a deep copy of \"lisa\" with the first_name replaced.\nconst auto maggie = rfl::replace(\n    lisa, rfl::make_field\u003c\"first_name\"\u003e(std::string(\"Maggie\")));\n```\n\nOr you can create structs from other structs:\n\n```cpp\nstruct A {\n  std::string f1;\n  std::string f2;\n};\n\nstruct B {\n  std::string f3;\n  std::string f4;\n};\n\nstruct C {\n  std::string f1;\n  std::string f2;\n  std::string f4;\n};\n\nconst auto a = A{.f1 = \"Hello\", .f2 = \"World\"};\n\nconst auto b = B{.f3 = \"Hello\", .f4 = \"World\"};\n\n// f1 and f2 are taken from a, f4 is taken from b, f3 is ignored.\nconst auto c = rfl::as\u003cC\u003e(a, b);\n```\n\nYou can also replace fields in structs using fields from other structs:\n\n```cpp\nconst auto a = A{.f1 = \"Hello\", .f2 = \"World\"};\n\nconst auto c = C{.f1 = \"C++\", .f2 = \"is\", .f4 = \"great\"};\n\n// The fields f1 and f2 are replaced with the fields f1 and f2 in a.\nconst auto c2 = rfl::replace(c, a);\n```\n\n\n### Support for containers\n\n#### C++ standard library\n\nreflect-cpp supports the following containers from the C++ standard library:\n\n- `std::array`\n- `std::deque`\n- `std::chrono::duration`\n- `std::filesystem::path`\n- `std::forward_list`\n- `std::map`\n- `std::multimap`\n- `std::multiset`\n- `std::list`\n- `std::optional`\n- `std::pair`\n- `std::set`\n- `std::shared_ptr`\n- `std::span`\n- `std::string`\n- `std::string_view`\n- `std::tuple`\n- `std::unique_ptr`\n- `std::unordered_map`\n- `std::unordered_multimap`\n- `std::unordered_multiset`\n- `std::unordered_set`\n- `std::variant`\n- `std::vector`\n- `std::wstring`\n\n#### Additional containers\n\nIn addition, it supports the following custom containers:\n\n- `rfl::Binary`: Used to express numbers in binary format.\n- `rfl::Box`: Similar to `std::unique_ptr`, but (almost) guaranteed to never be null.\n- `rfl::Bytestring`: An alias for `std::vector\u003cstd::byte\u003e`. Supported by Avro, BSON, Cap'n Proto, CBOR, flexbuffers, msgpack and UBJSON. \n- `rfl::Generic`: A catch-all type that can represent (almost) anything.\n- `rfl::Hex`: Used to express numbers in hex format.\n- `rfl::Literal`: An explicitly enumerated string.\n- `rfl::NamedTuple`: Similar to `std::tuple`, but with named fields that can be retrieved via their name at compile time.\n- `rfl::Object`: A map-like type representing a object with field names that are unknown at compile time.\n- `rfl::Oct`: Used to express numbers in octal format.\n- `rfl::Ref`: Similar to `std::shared_ptr`, but (almost) guaranteed to never be null.\n- `rfl::Result`: Allows for exception-free programming.\n- `rfl::TaggedUnion`: Similar to `std::variant`, but with explicit tags that make parsing more efficient.\n- `rfl::Tuple`: An alternative to `std::tuple` that compiles considerably faster.\n- `rfl::Validator`: Allows for automatic input validation.\n- `rfl::Variant`: An alternative to `std::variant` that compiles considerably faster.\n\n#### Custom classes\n\nFinally, it is very easy to extend full support to your own classes, refer to the [documentation](https://rfl.getml.com/docs-readme) for details.\n\n\n## Installation\n\nThe following compilers are supported:\n- GCC 11.4 or higher\n- Clang 14.0 or higher\n- MSVC 17.8 (19.38) or higher\n\n### Using vcpkg\n\nhttps://vcpkg.io/en/package/reflectcpp\n\n### Using Conan\n\nhttps://conan.io/center/recipes/reflect-cpp\n\n### Compilation using cmake\n\nThis will compile reflect-cpp with JSON support only. You can then include reflect-cpp in your project and link to the binary.\n\n```bash\ncmake -S . -B build -DCMAKE_CXX_STANDARD=20 -DCMAKE_BUILD_TYPE=Release\ncmake --build build -j 4  # gcc, clang\ncmake --build build --config Release -j 4  # MSVC\n```\n\nTo install all supported serialization formats, first install vcpkg:\n\n```bash\ngit submodule update --init\n./vcpkg/bootstrap-vcpkg.sh # Linux, macOS\n./vcpkg/bootstrap-vcpkg.bat # Windows\n# You may be prompted to install additional dependencies.\n```\n\nThen, compile the library:\n\n```bash\ncmake -S . -B build -DCMAKE_CXX_STANDARD=20 -DCMAKE_BUILD_TYPE=Release -DREFLECTCPP_ALL_FORMATS=ON\ncmake --build build -j 4 # gcc, clang\ncmake --build build --config Release -j 4 # MSVC\n```\n\nFor other installation methods, refer to the [documentation](https://rfl.getml.com/docs-readme).\n\n## The team behind reflect-cpp\n\nreflect-cpp has been developed by [getML (Code17 GmbH)](https://getml.com), a company specializing in software engineering and machine learning for enterprise applications. reflect-cpp is currently maintained by Patrick Urbanke and Manuel Bellersen, with major contributions coming from the community.\n\n### Related projects\n\nreflect-cpp was originally developed for [getml-community](https://github.com/getml/getml-community), the fastest open-source tool for feature engineering on relational data and time series. If you are interested in Data Science and/or Machine Learning, please check it out.\n\n### Professional C++ Support\n\nFor comprehensive C++ support beyond the scope of GitHub discussions, we’re here to help! Reach out at [support@getml.com](mailto:support%40getml.com?subject=C++%20support%20request) to discuss any technical challenges or project requirements. We’re excited to support your work as independent software consultants.\n\n\n## License\n\nreflect-cpp is released under the MIT License. Refer to the LICENSE file for details.\n\nreflect-cpp includes [YYJSON](https://github.com/ibireme/yyjson), the fastest JSON library currently in existence. YYJSON is written by YaoYuan and also released under the MIT License.\n\nreflect-cpp includes [compile-time-regular-expressions](https://github.com/hanickadot/compile-time-regular-expressions). CTRE is written by Hana Dusíková and released under the Apache-2.0 License with LLVM exceptions.\n\nreflect-cpp includes [enchantum](https://github.com/ZXShady/enchantum/tree/main). enchantum is written by ZXShady and also released under the MIT License.\n","funding_links":[],"categories":["Reflection","C++","反射","Program"],"sub_categories":["C/C++"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgetml%2Freflect-cpp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgetml%2Freflect-cpp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgetml%2Freflect-cpp/lists"}