{"id":13419689,"url":"https://github.com/netheril96/StaticJSON","last_synced_at":"2025-03-15T05:32:39.836Z","repository":{"id":20821550,"uuid":"24107334","full_name":"netheril96/StaticJSON","owner":"netheril96","description":"Fast, direct and static typed parsing of JSON with C++","archived":false,"fork":false,"pushed_at":"2023-01-09T02:31:46.000Z","size":719,"stargazers_count":198,"open_issues_count":2,"forks_count":35,"subscribers_count":18,"default_branch":"master","last_synced_at":"2024-11-04T05:34:34.845Z","etag":null,"topics":["c-plus-plus","json","json-schema","parsing"],"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/netheril96.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}},"created_at":"2014-09-16T16:15:54.000Z","updated_at":"2024-09-26T22:17:01.000Z","dependencies_parsed_at":"2022-09-08T05:11:43.363Z","dependency_job_id":null,"html_url":"https://github.com/netheril96/StaticJSON","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/netheril96%2FStaticJSON","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/netheril96%2FStaticJSON/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/netheril96%2FStaticJSON/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/netheril96%2FStaticJSON/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/netheril96","download_url":"https://codeload.github.com/netheril96/StaticJSON/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243690112,"owners_count":20331726,"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":["c-plus-plus","json","json-schema","parsing"],"created_at":"2024-07-30T22:01:19.412Z","updated_at":"2025-03-15T05:32:39.551Z","avatar_url":"https://github.com/netheril96.png","language":"C++","funding_links":[],"categories":["TODO scan for Android support in followings"],"sub_categories":[],"readme":"# StaticJSON\n\nFast, direct and static typed parsing of JSON with C++.\n\n## Overview\n\nJSON is a popular format for data exchange. Reading and writing JSON in C++, however, is nontrivial. Even with the help of libraries, one still needs to write lots of boilerplate code, and it is extremely hard to guard against all possible errors, since JSON is dynamically typed while C++ employs static typing.\n\nMore importantly, manually writing such code is a violation of **DRY** principle. When manually written, the class definition, parsing and serialization code can easily become out of sync, leading to brittle code and subtle bugs.\n\n`StaticJSON` is an attempt to solve this problem by automating such process.\n\n## Usage\n\n`StaticJSON` requires a C++11 compiler.\n\n## Method 1: use [vcpkg](https://vcpkg.io)\n\nRun command `vcpkg install staticjson`, then in your `CMakeLists.txt`, add\n\n```cmake\n find_package(staticjson CONFIG REQUIRED)\n target_link_libraries(${YOUR_TARGET} PRIVATE staticjson::staticjson)\n```\n\n## Method 2: just build everything together\n\nJust drop the `include` and `src` directory into your own project and build along with other sources. It requires you to separately install [`rapidjson`](https://rapidjson.org).\n\n## Quick start\n\n### Builtin types\n\n```c++\n#include \u003cstaticjson/staticjson.hpp\u003e\n\nint builtin_test() {\n    using namespace staticjson;\n    std::string a = to_json_string(std::vector\u003cdouble\u003e{1.0, 2.0, -3.1415});\n    std::string b = to_pretty_json_string(std::map\u003cstd::string, std::shared_ptr\u003cstd::list\u003cbool\u003e\u003e\u003e{});\n\n    std::vector\u003cstd::unordered_map\u003cstd::string, std::int64_t\u003e\u003e data;\n    const char* json_string = \"[{\\\" hello \\\": 535353, \\\" world \\\": 849},\"\n        \" {\\\" k \\\": -548343}]\";\n    assert(from_json_string(json_string, \u0026data, nullptr));\n    assert(data.size() == 2);\n    assert(data[1][\" k \"] == -548343);\n\n    to_pretty_json_file(stdout, data);\n    return 0;\n}\n```\n\n### Register custom class types\n\nFor your own classes, you need to add some definitions first before you can use the `from_json` and `to_json` functions. There are two ways of doing this.\n\n#### Intrusive definition\n\nThis way requires you to implement a special method in the class prototyped `void staticjson_init(staticjson::ObjectHandler* h)`. Example definition\n\n```c++\nstruct Date\n{\n    int year, month, day;\n\n    void staticjson_init(ObjectHandler* h)\n    {\n        h-\u003eadd_property(\"year\", \u0026year);\n        h-\u003eadd_property(\"month\", \u0026month);\n        h-\u003eadd_property(\"day\", \u0026day);\n        h-\u003eset_flags(Flags::DisallowUnknownKey);\n    }\n};\n\nstruct BlockEvent\n{\n    std::uint64_t serial_number, admin_ID = 255;\n    Date date;\n    std::string description, details;\n\n    void staticjson_init(ObjectHandler* h)\n    {\n        h-\u003eadd_property(\"serial_number\", \u0026serial_number);\n        h-\u003eadd_property(\"administrator ID\", \u0026admin_ID, Flags::Optional);\n        h-\u003eadd_property(\"date\", \u0026date, Flags::Optional);\n        h-\u003eadd_property(\"description\", \u0026description, Flags::Optional);\n        h-\u003eadd_property(\"details\", \u0026details, Flags::Optional);\n    }\n};\n```\n\n### Non-intrusive definition\n\nThis requires you to overload a special function for your custom class. For example, the `Date` overload is written as\n\n```c++\nnamespace staticjson\n{\nvoid init(Date* d, ObjectHandler* h)\n{\n    h-\u003eadd_property(\"year\", \u0026d-\u003eyear);\n    h-\u003eadd_property(\"month\", \u0026d-\u003emonth);\n    h-\u003eadd_property(\"day\", \u0026d-\u003eday);\n    h-\u003eset_flags(Flags::DisallowUnknownKey);\n}\n}\n```\n\nYou may need to declare `staticjson::init` as a friend function in order to access private and protected members.\n\n### Register enumeration types\n\nExample\n\n```c++\nenum class CalendarType\n{\n    Gregorian,\n    Chinese,\n    Jewish,\n    Islam\n};\n\nSTATICJSON_DECLARE_ENUM(CalendarType,\n                        {\"Gregorian\", CalendarType::Gregorian},\n                        {\"Chinese\", CalendarType::Chinese},\n                        {\"Jewish\", CalendarType::Jewish},\n                        {\"Islam\", CalendarType::Islam})\n```\n\nThis will convert the enum type to/from strings, and signal error if the string is not in the list.\n\nNote that this macro must not be instantiated inside a namespace.\n\n## Custom conversion\n\nIf you want a type to be serialized in a different way, such as a custom `Date` object as an ISO8601 string or an arbitrary precision integer as a list of 32-bit integers, you can enable the custom conversion for the type. To do so, specialize the template class in namespace `staticjson`\n\n```c++\nnamespace staticjson\n{\ntemplate \u003c\u003e\nstruct Converter\u003cDate\u003e\n{\n    typedef std::string shadow_type; \n    // This typedef is a must. The shadow type is a C++ type \n    // that can be directly converted to and from JSON values.\n\n    static std::unique_ptr\u003cErrorBase\u003e from_shadow(const shadow_type\u0026 shadow, Date\u0026 value)\n    {\n        bool success = value.parseISO8601(shadow);\n        if (success)\n            return nullptr;\n        return std::make_unique\u003cCustomError\u003e(\"Invalid ISO 8601 string\");\n    }\n\n    static void to_shadow(const Date\u0026 value, shadow_type\u0026 shadow)\n    {\n        shadow = value.toISO8601();\n    }\n};\n}\n\n```\n\n## Error handling\n\n`StaticJSON` strives not to let any mismatch between the C++ type specifications and the JSON object slip. It detects and reports all kinds of errors, including type mismatch, integer out of range, floating number precision loss, required fields missing, duplicate keys etc. Many of them can be tuned on or off. It also reports an stack trace in case of error (not actual C++ exception).\n\nThe third parameter of all `from_json` family of functions is a nullable pointer to `staticjson::ParseStatus` object. If present, the error information will be dumped into it. An example error message is\n\n```\nParsing failed at offset 1000 with error code 16:\nTerminate parsing due to Handler error.\n\nTraceback (last call first)\n* Type mismatch between expected type \"unsigned long long\" and actual type \"string\"\n* Error at object member with name \"serial_number\"\n* Error at array element at index 0\n* Error at object member with name \"dark_history\"\n* Error at array element at index 1\n```\n\n## List of builtin supported types\n\n* **Boolean types**: `bool`, `char`\n* **Integer types**: `int`, `unsigned int`, `long`, `unsigned long`, `long long`, `unsigned long long`\n* **Floating point types**: `float`, `double`\n* **String types**: `std::string`\n* **Array types**: `std::vector\u003c•\u003e`, `std::deque\u003c•\u003e`, `std::list\u003c•\u003e`, `std::array\u003c•\u003e`\n* **Nullable types**: `std::nullptr_t`, `std::unique_ptr\u003c•\u003e`, `std::shared_ptr\u003c•\u003e`\n* **Map types**: `std::{map, multimap, unordered_map, unordered_multimap}\u003cstd::string, •\u003e`\n* **Tuple types**: `std::tuple\u003c...\u003e`\n\n## Dynamic typing\n\nIf you need occasional escape from the rigidity of C++'s static type system, but do not want complete dynamism, you can still find the middle ground in `StaticJSON`.\n\n* You can embed a `staticjson::Document` (alias of `rapidjson::Document`) in your class/struct, which allows static typing for some class members and dynamic typing for others. Note `Document` is already nullable so do not use a smart pointer to `Document`.\n* You can convert a `Document` or `Value` to and from a C++ type registered in `StaticJSON`. The functions are aptly named `from_json_value`, `from_json_document`, `to_json_value`, `to_json_document`.\n\n\n## Export as JSON Schema\n\nFunction `export_json_schema` allows you to export the validation rules used by `StaticJSON` as JSON schema. It can then be used in other languages to do the similar validation. Note the two rules are only approximate match, because certain rules cannot be expressed in JSON schema yet, and because some languages have different treatments of numbers from C++.\n\n## Misc\n\nThe project was originally named *autojsoncxx* and requires a code generator to run.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnetheril96%2FStaticJSON","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnetheril96%2FStaticJSON","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnetheril96%2FStaticJSON/lists"}