{"id":44646782,"url":"https://github.com/geode-sdk/json","last_synced_at":"2026-02-14T20:08:03.122Z","repository":{"id":98990256,"uuid":"593375795","full_name":"geode-sdk/json","owner":"geode-sdk","description":"Simple json library that preserves insertion order. Made for Geode SDK","archived":false,"fork":false,"pushed_at":"2025-11-14T18:20:19.000Z","size":232,"stargazers_count":6,"open_issues_count":2,"forks_count":6,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-14T20:34:05.939Z","etag":null,"topics":["cpp","cpp-library","cpp20","json","json-parser"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsl-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/geode-sdk.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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-01-25T21:16:36.000Z","updated_at":"2025-11-14T18:19:09.000Z","dependencies_parsed_at":null,"dependency_job_id":"f2e6b578-362b-4766-9024-a822a30547fe","html_url":"https://github.com/geode-sdk/json","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/geode-sdk/json","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geode-sdk%2Fjson","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geode-sdk%2Fjson/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geode-sdk%2Fjson/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geode-sdk%2Fjson/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/geode-sdk","download_url":"https://codeload.github.com/geode-sdk/json/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/geode-sdk%2Fjson/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29454874,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-14T15:52:44.973Z","status":"ssl_error","status_checked_at":"2026-02-14T15:52:11.208Z","response_time":53,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["cpp","cpp-library","cpp20","json","json-parser"],"created_at":"2026-02-14T20:08:02.586Z","updated_at":"2026-02-14T20:08:03.112Z","avatar_url":"https://github.com/geode-sdk.png","language":"C++","readme":"# MATjson\n\nJSON library made for [Geode](https://github.com/geode-sdk/json). Main feature is preserving insertion order, along with the use of [Geode's Result library](https://github.com/geode-sdk/result).\n\n## Example\n\n```cpp\n#include \u003cmatjson.hpp\u003e\n\nauto result = matjson::parse(R\"(\n    {\n        \"hello\": \"world\",\n        \"foo\": {\n            \"bar\": 2000\n        }\n    }\n)\");\nif (!result) {\n    println(\"Failed to parse json: {}\", result.unwrapErr());\n}\nmatjson::Value object = result.unwrap();\n\nobject[\"hello\"].asString().unwrap(); // world\nobject[\"foo\"][\"bar\"].asInt().unwrap(); // 2000\nobject.isObject(); // true\nobject.isString(); // false\n```\n\n# Index\n\n* [Usage](#usage)\n    * [Parsing JSON](#parsing-json)\n    * [Dumping JSON](#dumping-json)\n    * [Accessing object properties](#accessing-object-properties)\n    * [Serializing custom types](#serializing-custom-types)\n    * [Objects and arrays](#objects-and-arrays)\n    * [Reflection](#reflection)\n    * [Support for standard library types](#support-for-standard-library-types)\n* [FAQ](#faq)\n    * [Why?](#why)\n\n# Usage\n\nThe main class of the library is `matjson::Value`, which can represent any JSON value. You can access its type by using the `type()` method, or one of the `isString()` methods.\n```cpp\nmatjson::Value value = ...;\n\nmatjson::Type type = value.type();\nif (type == matjson::Type::Object) {\n    // ...\n}\n// same as\nif (value.isObject()) {\n    // ...\n}\n```\n\nAnything not documented here can be found in the [matjson.hpp](https://github.com/geode-sdk/json/blob/main/include/matjson.hpp) header, which is also well documented.\n\n## Parsing JSON\n\nTo parse JSON into a `matjson::Value`, you can simply use the `matjson::parse` method\n\n```cpp\nResult\u003cmatjson::Value, matjson::ParseError\u003e matjson::parse(std::string_view str);\nResult\u003cmatjson::Value, matjson::ParseError\u003e matjson::parse(std::istream\u0026 stream);\n```\n```cpp\nGEODE_UNWRAP_INTO(matjson::Value value, matjson::parse(\"[1, 2, 3, 4]\"));\n\nstd::ifstream file(\"file.json\");\nGEODE_UNWRAP_INTO(matjson::Value value2, matjson::parse(file));\n```\n\n## Dumping JSON\n\nTo convert a `matjson::Value` back to a JSON string, use `dump()`\n```cpp\n/// Dumps the JSON value to a string, with a given indentation.\n/// If the given indentation is matjson::NO_INDENTATION, the json is compacted.\n/// If the given indentation is matjson::TAB_INDENTATION, the json is indented with tabs.\n/// @param indentationSize The number of spaces to use for indentation\n/// @return The JSON string\n/// @note Due to limitations in the JSON format, NaN and Infinity float values get converted to null.\n///       This behavior is the same as many other JSON libraries.\nstd::string Value::dump(int indentation = 4);\n```\n```cpp\nmatjson::Value object = matjson::makeObject({\n    {\"x\", 10}\n});\n\nstd::string jsonStr = object.dump();\n// {\n//     \"x\": 10\n// }\n\nstd::string compact = object.dump(matjson::NO_INDENTATION);\n// {\"x\":10}\n```\n\n## Accessing object properties\n\nThere are many different ways to access inner properties\n```cpp\nResult\u003cValue\u0026\u003e Value::get(std::string_view key);\nResult\u003cValue\u0026\u003e Value::get(std::size_t index);\n// These are special!\nValue\u0026 Value::operator[](std::string_view key);\nValue\u0026 Value::operator[](std::size_t index);\n```\nAs noted, `operator[]` is special because:\n* If the `matjson::Value` is not const, `operator[](std::string_view key)` will insert into the object, akin to `std::map`. \\\n(This does not apply if the value is an array)\n* Otherwise, trying to access missing values will return a special `null` JSON value. This value cannot be mutated.\n```cpp\nmatjson::Value object = matjson::parse(R\"(\n    {\n        \"hello\": \"world\",\n        \"foo\": {\n            \"bar\": 2000\n            \"numbers\": [123, false, \"not a number actually\"]\n        }\n    }\n)\").unwrap();\n\nobject[\"hello\"]; // matjson::Value(\"world\")\nobject.get(\"hello\"); // Ok(matjson::Value(\"world\"))\n\nobject[\"foo\"][\"bar\"].asInt(); // Ok(2000)\n\nobject.contains(\"sup\"); // false\n\n// will insert \"sup\" into object as long as its not const.\n// behaves like std::map::operator[]\nobject[\"sup\"];\nobject[\"nya\"] = 123;\n\n// not the case for .get\nobject.get(\"something else\"); // Err(\"key not found\")\n```\n\n## Serializing custom types\n\nIt's possible to (de)serialize your own types into json, by specializing `matjson::Serialize\u003cT\u003e`.\n```cpp\n#include \u003cmatjson.hpp\u003e\n\nstruct User {\n    std::string name;\n    int age;\n};\n\ntemplate \u003c\u003e\nstruct matjson::Serialize\u003cUser\u003e {\n    static geode::Result\u003cUser\u003e fromJson(const matjson::Value\u0026 value) {\n        GEODE_UNWRAP_INTO(std::string name, value[\"name\"].asString());\n        GEODE_UNWRAP_INTO(int age, value[\"age\"].asInt());\n        return geode::Ok(User { name, age });\n    }\n    static matjson::Value toJson(const User\u0026 user) {\n        return matjson::makeObject({\n            { \"name\", user.name },\n            { \"age\", user.age }\n        });\n    }\n};\n\nint main() {\n    User user = { \"mat\", 123 };\n\n    // gets implicitly converted into json\n    matjson::Value value = user;\n\n    value.dump(matjson::NO_INDENTATION); // {\"name\":\"mat\",\"age\":123}\n\n    value[\"name\"] = \"hello\";\n    // you have to use the templated methods for accessing custom types!\n    // it will *not* implicitly convert to User\n    User user2 = value.as\u003cUser\u003e().unwrap();\n    user2.name; // \"hello\"\n}\n```\n\nSerialization is available for many standard library containers in `#include \u003cmatjson/std.hpp\u003e`, as mentioned in [Support for standard library types](#support-for-standard-library-types).\n\nThere is also experimental support for [reflection](#reflection).\n\n## Objects and arrays\n\nObjects and arrays have special methods, since they can be iterated and mutated.\n```cpp\n// Does nothing if Value is not an object\nvoid Value::set(std::string_view key, Value value);\n// Does nothing if Value is not an array\nvoid Value::push(Value value);\n// Clears all entries from an array or object\nvoid Value::clear();\n// Does nothing if Value is not an object\nbool Value::erase(std::string_view key);\n// Returns 0 if Value is not an object or array\nstd::size_t Value::size() const;\n```\nTo make objects you can use the `matjson::makeObject` function, and for arrays you can use the `Value::Value(std::vector\u003cmatjson::Value\u003e)` constructor.\n```cpp\nmatjson::Value obj = matjson::makeObject({\n    {\"hello\", \"world\"},\n    {\"number\", \"123\"}\n});\n\nfor (auto\u0026 [key, value] : obj) {\n    // key is std::string\n    // value is matjson::Value\n}\n\n// just iterates through the values\nfor (auto\u0026 value : obj) {\n    // value is matjson::Value\n}\n\nobj.set(\"foo\", true);\n\nmatjson::Value arr({ 1, 2, \"hello\", true });\narr[0]; // 1\narr[2]; // \"hello\"\narr[9]; // null\narr.get(9); // Err(\"index out of bounds\")\n\nfor (auto\u0026 value : obj) {\n    // values\n}\n\narr.push(nullptr);\narr.dump(matjson::NO_INDENTATION); // [1,2,\"hello\",true,null]\n\n// If you need direct access to the vector, for some reason\nstd::vector\u003cmatjson::Value\u003e\u0026 vec = arr.asArray().unwrap();\n```\n\n## Reflection\n\nThe library now has experimental support for reflection using the [qlibs/reflect](https://github.com/qlibs/reflect) library, which only supports [aggregate types](https://en.cppreference.com/w/cpp/language/aggregate_initialization).\n\nIncluding the optional header will define JSON serialization for any type it can, making them able to be used with matjson instantly\n\n```cpp\n#include \u003cmatjson/reflect.hpp\u003e\n\nstruct Stats {\n    int hunger;\n    int health;\n};\n\nstruct User {\n    std::string name;\n    Stats stats;\n    bool registered;\n};\n\nint main() {\n    User user = User {\n        .name = \"Joe\",\n        .stats = Stats {\n            .hunger = 0,\n            .health = 100\n        },\n        .registered = true\n    };\n\n    matjson::Value value = user;\n\n    value.dump();\n    // {\n    //     \"name\": \"Joe\",\n    //     \"stats\": {\n    //         \"hunger\": 0,\n    //         \"health\": 0\n    //     },\n    //     \"registered\": true\n    // }\n\n    User u2 = value.as\u003cUser\u003e().unwrap();\n}\n```\n\n## Support for standard library types\n\nThere is built in support for serializing std containers by including an optional header:\n\nSupported classes (given T is serializable):\n* `std::vector\u003cT\u003e`\n* `std::array\u003cT, N\u003e`\n* `std::span\u003cT\u003e`\n* `std::map\u003cstd::string, T\u003e`\n* `std::unordered_map\u003cstd::string, T\u003e`\n* `std::set\u003cT\u003e`\n* `std::unordered_set\u003cT\u003e`\n* `std::optional\u003cT\u003e` - `null` is prioritized as `std::nullopt`\n* `std::shared_ptr\u003cT\u003e` - same as above\n* `std::unique_ptr\u003cT\u003e` - same as above\n\n```cpp\n#include \u003cmatjson/std.hpp\u003e\n\nstd::vector\u003cint\u003e nums = { 1, 2, 3 };\nstd::map\u003cstd::string, std::string\u003e map = {\n    { \"hello\", \"foo\" }\n};\n\nmatjson::Value jsonNums = nums;\nmatjson::Value jsonMap = map;\n```\n\n# FAQ\n\n## Why?\n\nThis library was initially made due to concerns of the compile speeds of [nlohmann/json](https://github.com/nlohmann/json), which was included all over the place in geode. \\\nNowadays the main benefit of this library is integration with [Geode's Result type](https://github.com/geode-sdk/result).\n\nMods can use whatever JSON library they want to, if matjson doesnt fit their needs\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeode-sdk%2Fjson","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgeode-sdk%2Fjson","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeode-sdk%2Fjson/lists"}