{"id":30237729,"url":"https://github.com/wenzhang-dev/reflpp","last_synced_at":"2026-04-18T09:31:07.824Z","repository":{"id":307648377,"uuid":"1025980099","full_name":"wenzhang-dev/reflpp","owner":"wenzhang-dev","description":"A C++20 library for fast serialization and deserialization using reflection","archived":false,"fork":false,"pushed_at":"2025-08-02T05:17:58.000Z","size":28,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-08-15T02:18:59.251Z","etag":null,"topics":["aggregate-struct","cxx20","header-only","json","modern-cpp","non-intrusive","reflection"],"latest_commit_sha":null,"homepage":"","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/wenzhang-dev.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":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-07-25T05:54:32.000Z","updated_at":"2025-08-02T05:18:01.000Z","dependencies_parsed_at":"2025-08-02T04:46:14.946Z","dependency_job_id":null,"html_url":"https://github.com/wenzhang-dev/reflpp","commit_stats":null,"previous_names":["wenzhang-dev/reflpp"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/wenzhang-dev/reflpp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wenzhang-dev%2Freflpp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wenzhang-dev%2Freflpp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wenzhang-dev%2Freflpp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wenzhang-dev%2Freflpp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wenzhang-dev","download_url":"https://codeload.github.com/wenzhang-dev/reflpp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wenzhang-dev%2Freflpp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31963922,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-18T00:39:45.007Z","status":"online","status_checked_at":"2026-04-18T02:00:07.018Z","response_time":103,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["aggregate-struct","cxx20","header-only","json","modern-cpp","non-intrusive","reflection"],"created_at":"2025-08-15T02:09:13.498Z","updated_at":"2026-04-18T09:31:07.805Z","avatar_url":"https://github.com/wenzhang-dev.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# reflpp\n\nreflpp is a lightweight, non-intrusive reflection library. It is implemented based on cxx20. The library makes it easy to iterate over the members of a struct, get the number of members, get the name of the member, and json serialization and deserialization. The most important feature is that it is non-intrusive. There is no need to use macros or registers to declare which fields the struct has, the address offset of each field.\n\nWhile everything looks nice, it's limited to the aggregate type.\n\n# Dependency\n\n- cxx20\n- fmtlib\n\n# Example\n\n```c++\n#include \u003cfmt/core.h\u003e\n#include \u003cfmt/ranges.h\u003e\n#include \u003cfmt/std.h\u003e\n#include \u003creflpp.h\u003e\n\n#include \u003carray\u003e\n#include \u003ciostream\u003e\n#include \u003cmemory\u003e\n#include \u003coptional\u003e\n#include \u003cstring\u003e\n#include \u003ctuple\u003e\n#include \u003cvector\u003e\n\ntemplate \u003ctypename T\u003e\nstruct fmt::formatter\u003cstd::unique_ptr\u003cT\u003e\u003e {\n    constexpr auto parse(fmt::format_parse_context\u0026 ctx) { return ctx.begin(); }\n\n    template \u003ctypename FormatContext\u003e\n    auto format(const std::unique_ptr\u003cT\u003e\u0026 ptr, FormatContext\u0026 ctx) const {\n        if (ptr)\n            return fmt::format_to(ctx.out(), \"{}\", *ptr);\n        else\n            return fmt::format_to(ctx.out(), \"null\");\n    }\n};\n\ntemplate \u003ctypename T\u003e\nstruct fmt::formatter\u003cstd::shared_ptr\u003cT\u003e\u003e {\n    constexpr auto parse(fmt::format_parse_context\u0026 ctx) { return ctx.begin(); }\n\n    template \u003ctypename FormatContext\u003e\n    auto format(const std::shared_ptr\u003cT\u003e\u0026 ptr, FormatContext\u0026 ctx) const {\n        if (ptr)\n            return fmt::format_to(ctx.out(), \"{}\", *ptr);\n        else\n            return fmt::format_to(ctx.out(), \"null\");\n    }\n};\n\nstruct Foo {\n    int a;\n    bool b;\n    double c;\n\n    std::string d;\n    std::vector\u003cstd::string\u003e e;\n    std::array\u003cint, 3\u003e f;\n\n    std::map\u003cstd::string, std::string\u003e g;\n    std::set\u003cint\u003e h;\n\n    std::optional\u003cint\u003e i;\n    std::unique_ptr\u003cstd::string\u003e j;\n};\n\nstruct Bar {\n    Foo foo;\n\n    double f64;\n    std::string str;\n};\n\nint main() {\n    std::cout \u003c\u003c \"The number of fields for Foo: \"\n              \u003c\u003c ::reflpp::FieldsCount\u003cFoo\u003e() \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"The number of fields for Bar: \"\n              \u003c\u003c ::reflpp::FieldsCount\u003cBar\u003e() \u003c\u003c std::endl;\n\n    std::cout \u003c\u003c \"The field names of Foo: \"\n              \u003c\u003c fmt::format(\"{}\", ::reflpp::kFieldNames\u003cFoo\u003e) \u003c\u003c std::endl;\n    std::cout \u003c\u003c \"The field names of Bar: \"\n              \u003c\u003c fmt::format(\"{}\", ::reflpp::kFieldNames\u003cBar\u003e) \u003c\u003c std::endl;\n\n    // clang-format off\n    Bar bar{\n        .foo={\n            1,\n            false,\n            3.14,\n            \"456\",\n            {\"789\", \"123\", \"456\"},\n            {7, 8, 9},\n            {std::make_pair(\"1\", \"2\"), std::make_pair(\"3\", \"4\")},\n            {7, 8, 9},\n            1,\n            std::make_unique\u003cstd::string\u003e(\"234\")\n        },\n        .f64=1.23,\n        .str=\"789\"\n    };\n    // clang-format on\n\n    std::cout \u003c\u003c \"Iterate Foo struct: \" \u003c\u003c std::endl;\n    ::reflpp::ForEach(bar.foo, [](auto idx, const auto\u0026 v) {\n        std::cout \u003c\u003c fmt::format(\"The field idx: {}, value: {}\", idx, v)\n                  \u003c\u003c std::endl;\n    });\n\n    std::cout \u003c\u003c \"Json serialization: \" \u003c\u003c std::endl;\n\n    ::reflpp::json::CompactJsonFormatter stream;\n    ::reflpp::json::ToJson(stream, bar);\n\n    std::cout \u003c\u003c stream \u003c\u003c std::endl;\n\n    std::cout \u003c\u003c \"Json deserialization: \" \u003c\u003c std::endl;\n    Bar bar1;\n\n    std::string_view json_str = R\"\"\"(\n    {\"foo\":{\"a\":1,\"b\":false,\"c\":3.14,\"d\":\"456\",\"e\":[\"789\",\"123\",\"456\"],\"f\":[7,8,9],\"g\":{\"1\":\"2\",\"3\":\"4\"},\"h\":[7,8,9],\"i\":1,\"j\":\"234\"},\"f64\":1.23,\"str\":\"789\"}\n    )\"\"\";\n    auto ec = ::reflpp::json::FromJson(json_str, bar1);\n    REFLPP_ASSERT(!ec);\n\n    ::reflpp::ForEach(bar1.foo, [](auto idx, const auto\u0026 v) {\n        std::cout \u003c\u003c fmt::format(\"The field idx: {}, value: {}\", idx, v)\n                  \u003c\u003c std::endl;\n    });\n\n    return 0;\n}\n```\n\nThe output from the example program is as follows:\n\n```txt\nThe number of fields for Foo: 10\nThe number of fields for Bar: 3\nThe field names of Foo: [\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\", \"i\", \"j\"]\nThe field names of Bar: [\"foo\", \"f64\", \"str\"]\nIterate Foo struct:\nThe field idx: 0, value: 1\nThe field idx: 1, value: false\nThe field idx: 2, value: 3.14\nThe field idx: 3, value: 456\nThe field idx: 4, value: [\"789\", \"123\", \"456\"]\nThe field idx: 5, value: [7, 8, 9]\nThe field idx: 6, value: {\"1\": \"2\", \"3\": \"4\"}\nThe field idx: 7, value: {7, 8, 9}\nThe field idx: 8, value: optional(1)\nThe field idx: 9, value: 234\nJson serialization:\n{\"foo\":{\"a\":1,\"b\":false,\"c\":3.14,\"d\":\"456\",\"e\":[\"789\",\"123\",\"456\"],\"f\":[7,8,9],\"g\":{\"1\":\"2\",\"3\":\"4\"},\"h\":[7,8,9],\"i\":1,\"j\":\"234\"},\"f64\":1.23,\"str\":\"789\"}\nJson deserialization:\nThe field idx: 0, value: 1\nThe field idx: 1, value: false\nThe field idx: 2, value: 3.14\nThe field idx: 3, value: 456\nThe field idx: 4, value: [\"789\", \"123\", \"456\"]\nThe field idx: 5, value: [7, 8, 9]\nThe field idx: 6, value: {\"1\": \"2\", \"3\": \"4\"}\nThe field idx: 7, value: {7, 8, 9}\nThe field idx: 8, value: optional(1)\nThe field idx: 9, value: 234\n```\n\nFor non-aggragate types, it is possible to use reflpp::Value to complete serialization. Here's an example:\n\n```c++\n#include \u003cfmt/core.h\u003e\n#include \u003cfmt/ranges.h\u003e\n#include \u003cfmt/std.h\u003e\n#include \u003creflpp.h\u003e\n\n#include \u003carray\u003e\n#include \u003ciostream\u003e\n#include \u003cmemory\u003e\n#include \u003coptional\u003e\n#include \u003cstring\u003e\n#include \u003ctuple\u003e\n#include \u003cvector\u003e\n\ntemplate \u003ctypename T\u003e\nstruct fmt::formatter\u003cstd::unique_ptr\u003cT\u003e\u003e {\n    constexpr auto parse(fmt::format_parse_context\u0026 ctx) { return ctx.begin(); }\n\n    template \u003ctypename FormatContext\u003e\n    auto format(const std::unique_ptr\u003cT\u003e\u0026 ptr, FormatContext\u0026 ctx) const {\n        if (ptr)\n            return fmt::format_to(ctx.out(), \"{}\", *ptr);\n        else\n            return fmt::format_to(ctx.out(), \"null\");\n    }\n};\n\ntemplate \u003ctypename T\u003e\nstruct fmt::formatter\u003cstd::shared_ptr\u003cT\u003e\u003e {\n    constexpr auto parse(fmt::format_parse_context\u0026 ctx) { return ctx.begin(); }\n\n    template \u003ctypename FormatContext\u003e\n    auto format(const std::shared_ptr\u003cT\u003e\u0026 ptr, FormatContext\u0026 ctx) const {\n        if (ptr)\n            return fmt::format_to(ctx.out(), \"{}\", *ptr);\n        else\n            return fmt::format_to(ctx.out(), \"null\");\n    }\n};\n\nclass ComplexBaseClass {\n   public:\n    virtual ~ComplexBaseClass() {}\n    virtual void DoSomething() = 0;\n};\n\nclass ComplexClass : public ComplexBaseClass {\n   public:\n    ComplexClass(int a, bool b, double c, std::string_view d)\n        : a_(a), b_(b), c_(c), d_(d) {}\n\n    void DoSomething() override {\n        std::cout \u003c\u003c a_ \u003c\u003c b_ \u003c\u003c c_ \u003c\u003c d_ \u003c\u003c std::endl;\n    }\n\n    void Dump(::reflpp::Value\u0026 v) {\n        auto\u0026 d = v.AsDirectory();\n        d[\"a\"] = a_;\n        d[\"b\"] = b_;\n        d[\"c\"] = c_;\n        d[\"d\"] = d_;\n    }\n\n   private:\n    int a_;\n    bool b_;\n    double c_;\n    std::string d_;\n};\n\nint main() {\n    std::cout \u003c\u003c \"Json serialization: \" \u003c\u003c std::endl;\n\n    ComplexClass cc(1, false, 3.14, \"456\");\n    ::reflpp::Value v;\n\n    cc.Dump(v);\n\n    ::reflpp::json::CompactJsonFormatter stream;\n    ::reflpp::json::ToJson(stream, v);\n\n    std::cout \u003c\u003c stream \u003c\u003c std::endl;\n\n    std::cout \u003c\u003c \"Json deserialization\" \u003c\u003c std::endl;\n\n    ::reflpp::Value v1;\n    auto json_str = R\"\"\"({\"a\":1,\"b\":false,\"c\":3.14,\"d\":\"456\"})\"\"\";\n    auto ec = ::reflpp::json::FromJson(json_str, v1);\n    REFLPP_ASSERT(!ec);\n\n    auto\u0026 dict = *v1.ToDirectory();\n    for(auto\u0026 kv : dict) {\n        std::cout \u003c\u003c \"key: \" \u003c\u003c kv.first \u003c\u003c std::endl;\n    }\n\n    return 0;\n}\n```\n\nThe output from the example program is as follows:\n\n```txt\nJson serialization:\n{\"a\":1,\"b\":false,\"c\":3.14,\"d\":\"456\"}\nJson deserialization\nkey: a\nkey: b\nkey: c\nkey: d\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwenzhang-dev%2Freflpp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwenzhang-dev%2Freflpp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwenzhang-dev%2Freflpp/lists"}