diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2ec74c90..7b7bc4c0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -80,7 +80,7 @@ include(cmake/CPM.cmake)
 if (PROJECT_IS_TOP_LEVEL AND NOT GEODE_BUILDING_DOCS)
 	set(MAT_JSON_AS_INTERFACE ON)
 endif()
-CPMAddPackage("gh:geode-sdk/json#a47f570")
+CPMAddPackage("gh:geode-sdk/json#9f54cca")
 CPMAddPackage("gh:fmtlib/fmt#10.1.1")
 CPMAddPackage("gh:gulrak/filesystem#3e5b930")
 
diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt
index 2b597fa1..fd0d9f50 100644
--- a/loader/CMakeLists.txt
+++ b/loader/CMakeLists.txt
@@ -220,7 +220,7 @@ if (NOT GEODE_BUILDING_DOCS)
 	target_link_libraries(${PROJECT_NAME} md4c re2 minizip)
 endif()
 
-target_link_libraries(${PROJECT_NAME} z TulipHook geode-sdk mat-json)
+target_link_libraries(${PROJECT_NAME} z TulipHook geode-sdk mat-json-impl)
 
 if (MSVC)
 	# Disable outputting .exp file
diff --git a/loader/include/Geode/cocos/base_nodes/CCNode.h b/loader/include/Geode/cocos/base_nodes/CCNode.h
index 768fab5e..d9b3b704 100644
--- a/loader/include/Geode/cocos/base_nodes/CCNode.h
+++ b/loader/include/Geode/cocos/base_nodes/CCNode.h
@@ -39,7 +39,7 @@
 #include "../include/CCProtocols.h"
 #include "Layout.hpp"
 #include "../../loader/Event.hpp"
-#include <json.hpp>
+#include <matjson.hpp>
 
 NS_CC_BEGIN
 
@@ -845,7 +845,7 @@ private:
     friend class geode::modifier::FieldContainer;
 
     GEODE_DLL geode::modifier::FieldContainer* getFieldContainer();
-    GEODE_DLL std::optional<json::Value> getAttributeInternal(std::string const& attribute);
+    GEODE_DLL std::optional<matjson::Value> getAttributeInternal(std::string const& attribute);
     GEODE_DLL void addEventListenerInternal(
         std::string const& id,
         geode::EventListenerProtocol* protocol
@@ -935,7 +935,7 @@ public:
      * @param value The value of the attribute
      * @note Geode addition
      */
-    GEODE_DLL void setAttribute(std::string const& attribute, json::Value const& value);
+    GEODE_DLL void setAttribute(std::string const& attribute, matjson::Value const& value);
     /**
      * Get an attribute from the node. Attributes may be anything
      * @param attribute The attribute key
@@ -1772,9 +1772,9 @@ namespace geode {
     struct GEODE_DLL AttributeSetEvent : public Event {
         cocos2d::CCNode* node;
         const std::string id;
-        json::Value& value;
+        matjson::Value& value;
 
-        AttributeSetEvent(cocos2d::CCNode* node, std::string const& id, json::Value& value);
+        AttributeSetEvent(cocos2d::CCNode* node, std::string const& id, matjson::Value& value);
     };
 
     class GEODE_DLL AttributeSetFilter : public EventFilter<AttributeSetEvent> {
diff --git a/loader/include/Geode/loader/Hook.hpp b/loader/include/Geode/loader/Hook.hpp
index 6d931365..eb11ddfc 100644
--- a/loader/include/Geode/loader/Hook.hpp
+++ b/loader/include/Geode/loader/Hook.hpp
@@ -2,7 +2,7 @@
 
 #include "../DefaultInclude.hpp"
 #include "../utils/general.hpp"
-#include <json.hpp>
+#include <matjson.hpp>
 #include "Tulip.hpp"
 #include <inttypes.h>
 #include <string_view>
@@ -104,7 +104,7 @@ namespace geode {
          * Get info about the hook as JSON
          * @note For IPC
          */
-        json::Value getRuntimeInfo() const;
+        matjson::Value getRuntimeInfo() const;
 
         /**
          * Get the metadata of the hook.
@@ -194,7 +194,7 @@ namespace geode {
          * Get info about the patch as JSON
          * @note For IPC
          */
-        json::Value getRuntimeInfo() const;
+        matjson::Value getRuntimeInfo() const;
 
         /**
         * Get whether the patch should be auto enabled or not.
diff --git a/loader/include/Geode/loader/IPC.hpp b/loader/include/Geode/loader/IPC.hpp
index 7d6444bc..eaa2e1f7 100644
--- a/loader/include/Geode/loader/IPC.hpp
+++ b/loader/include/Geode/loader/IPC.hpp
@@ -2,7 +2,7 @@
 
 #include "Event.hpp"
 #include "Loader.hpp"
-#include <json.hpp>
+#include <matjson.hpp>
 
 namespace geode {
     #ifdef GEODE_IS_WINDOWS
@@ -32,8 +32,8 @@ namespace geode {
     public:
         std::string targetModID;
         std::string messageID;
-        std::unique_ptr<json::Value> messageData;
-        json::Value& replyData;
+        std::unique_ptr<matjson::Value> messageData;
+        matjson::Value& replyData;
 
         friend class IPCFilter;
 
@@ -41,15 +41,15 @@ namespace geode {
             void* rawPipeHandle,
             std::string const& targetModID,
             std::string const& messageID,
-            json::Value const& messageData,
-            json::Value& replyData
+            matjson::Value const& messageData,
+            matjson::Value& replyData
         );
         virtual ~IPCEvent();
     };
 
     class GEODE_DLL IPCFilter : public EventFilter<IPCEvent> {
     public:
-        using Callback = json::Value(IPCEvent*);
+        using Callback = matjson::Value(IPCEvent*);
 
     protected:
         std::string m_modID;
@@ -64,5 +64,5 @@ namespace geode {
         IPCFilter(IPCFilter const&) = default;
     };
 
-    std::monostate listenForIPC(std::string const& messageID, json::Value(*callback)(IPCEvent*));
+    std::monostate listenForIPC(std::string const& messageID, matjson::Value(*callback)(IPCEvent*));
 }
diff --git a/loader/include/Geode/loader/Mod.hpp b/loader/include/Geode/loader/Mod.hpp
index 5d291961..5c75aa81 100644
--- a/loader/include/Geode/loader/Mod.hpp
+++ b/loader/include/Geode/loader/Mod.hpp
@@ -10,7 +10,7 @@
 #include "Setting.hpp"
 #include "Types.hpp"
 
-#include <json.hpp>
+#include <matjson.hpp>
 #include <optional>
 #include <string_view>
 #include <tulip/TulipHook.hpp>
@@ -151,7 +151,7 @@ namespace geode {
             this->registerCustomSetting(key, std::make_unique<T>(key, this->getID(), value));
         }
 
-        json::Value& getSaveContainer();
+        matjson::Value& getSaveContainer();
 
         template <class T>
         T getSettingValue(std::string const& key) const {
diff --git a/loader/include/Geode/loader/ModJsonTest.hpp b/loader/include/Geode/loader/ModJsonTest.hpp
index 6d536286..0188baef 100644
--- a/loader/include/Geode/loader/ModJsonTest.hpp
+++ b/loader/include/Geode/loader/ModJsonTest.hpp
@@ -1,5 +1,5 @@
 #include "Mod.hpp"
 
-#include <json.hpp>
+#include <matjson.hpp>
 
 namespace geode {}
\ No newline at end of file
diff --git a/loader/include/Geode/loader/ModMetadata.hpp b/loader/include/Geode/loader/ModMetadata.hpp
index ae009eeb..34d43df2 100644
--- a/loader/include/Geode/loader/ModMetadata.hpp
+++ b/loader/include/Geode/loader/ModMetadata.hpp
@@ -5,7 +5,7 @@
 #include "Setting.hpp"
 #include "Types.hpp"
 
-#include <json.hpp>
+#include <matjson.hpp>
 #include <memory>
 
 namespace geode {
@@ -228,8 +228,8 @@ namespace geode {
 }
 
 template <>
-struct json::Serialize<geode::ModMetadata> {
-    static json::Value to_json(geode::ModMetadata const& info) {
+struct matjson::Serialize<geode::ModMetadata> {
+    static matjson::Value to_json(geode::ModMetadata const& info) {
         return info.toJSON();
     }
 };
diff --git a/loader/include/Geode/loader/Setting.hpp b/loader/include/Geode/loader/Setting.hpp
index 5425687a..3b97e42e 100644
--- a/loader/include/Geode/loader/Setting.hpp
+++ b/loader/include/Geode/loader/Setting.hpp
@@ -4,7 +4,7 @@
 #include "../DefaultInclude.hpp"
 #include "../utils/Result.hpp"
 #include "../utils/file.hpp"
-#include <json.hpp>
+#include <matjson.hpp>
 #include <optional>
 #include <unordered_set>
 #include <cocos2d.h>
@@ -230,8 +230,8 @@ namespace geode {
     
     public:
         virtual ~SettingValue() = default;
-        virtual bool load(json::Value const& json) = 0;
-        virtual bool save(json::Value& json) const = 0;
+        virtual bool load(matjson::Value const& json) = 0;
+        virtual bool save(matjson::Value& json) const = 0;
         virtual SettingNode* createNode(float width) = 0;
 
         std::string getKey() const;
@@ -257,8 +257,8 @@ namespace geode {
             m_definition(definition),
             m_value(definition.defaultValue) {}
 
-        bool load(json::Value const& json) override;
-        bool save(json::Value& json) const;
+        bool load(matjson::Value const& json) override;
+        bool save(matjson::Value& json) const;
 
         GEODE_DLL SettingNode* createNode(float width) override;
         T castDefinition() const {
diff --git a/loader/include/Geode/loader/SettingJsonTest.hpp b/loader/include/Geode/loader/SettingJsonTest.hpp
index 66ac5e47..0398a2a8 100644
--- a/loader/include/Geode/loader/SettingJsonTest.hpp
+++ b/loader/include/Geode/loader/SettingJsonTest.hpp
@@ -1,9 +1,9 @@
 #include "Setting.hpp"
-#include <json.hpp>
+#include <matjson.hpp>
 
 namespace geode {
     template<class T>
-    bool GeodeSettingValue<T>::load(json::Value const& json) {
+    bool GeodeSettingValue<T>::load(matjson::Value const& json) {
         try {
             m_value = json.as<ValueType>();
             return true;
@@ -14,7 +14,7 @@ namespace geode {
     }
 
     template<class T>
-    bool GeodeSettingValue<T>::save(json::Value& json) const {
+    bool GeodeSettingValue<T>::save(matjson::Value& json) const {
         json = m_value;
         return true;
     }
diff --git a/loader/include/Geode/loader/Types.hpp b/loader/include/Geode/loader/Types.hpp
index 2caf1fa0..d33b0b4a 100644
--- a/loader/include/Geode/loader/Types.hpp
+++ b/loader/include/Geode/loader/Types.hpp
@@ -2,7 +2,7 @@
 
 #include "../DefaultInclude.hpp"
 #include "../platform/cplatform.h"
-#include <json.hpp>
+#include <matjson.hpp>
 
 #include <string>
 
@@ -146,7 +146,7 @@ namespace geode {
     }
 
     // TODO: make ordered
-    using ModJson = json::Value;
+    using ModJson = matjson::Value;
 }
 
 /**
diff --git a/loader/include/Geode/utils/JsonValidation.hpp b/loader/include/Geode/utils/JsonValidation.hpp
index 188631b9..42a4b861 100644
--- a/loader/include/Geode/utils/JsonValidation.hpp
+++ b/loader/include/Geode/utils/JsonValidation.hpp
@@ -1,6 +1,6 @@
 #pragma once
 
-#include <json.hpp>
+#include <matjson.hpp>
 #include "../loader/Log.hpp"
 
 #include <set>
@@ -21,7 +21,7 @@ namespace geode {
     constexpr bool is_iterable_v = is_iterable<T>::value;
 
     namespace {
-        using value_t = json::Type;
+        using value_t = matjson::Type;
 
         constexpr char const* jsonValueTypeToString(value_t type) {
             switch (type) {
@@ -80,7 +80,7 @@ namespace geode {
     struct GEODE_DLL JsonMaybeSomething {
     protected:
         JsonChecker& m_checker;
-        json::Value& m_json;
+        matjson::Value& m_json;
         std::string m_hierarchy;
         bool m_hasValue;
 
@@ -90,10 +90,10 @@ namespace geode {
         void setError(std::string const& error);
 
     public:
-        json::Value& json();
+        matjson::Value& json();
 
         JsonMaybeSomething(
-            JsonChecker& checker, json::Value& json, std::string const& hierarchy, bool hasValue
+            JsonChecker& checker, matjson::Value& json, std::string const& hierarchy, bool hasValue
         );
 
         bool isError() const;
@@ -106,12 +106,12 @@ namespace geode {
         bool m_inferType = true;
 
         JsonMaybeValue(
-            JsonChecker& checker, json::Value& json, std::string const& hierarchy, bool hasValue
+            JsonChecker& checker, matjson::Value& json, std::string const& hierarchy, bool hasValue
         );
 
         JsonMaybeSomething& self();
 
-        template <json::Type T>
+        template <matjson::Type T>
         JsonMaybeValue& as() {
             if (this->isError()) return *this;
             if (!jsonConvertibleTo(self().m_json.type(), T)) {
@@ -126,7 +126,7 @@ namespace geode {
 
         JsonMaybeValue& array();
 
-        template <json::Type... T>
+        template <matjson::Type... T>
         JsonMaybeValue& asOneOf() {
             if (this->isError()) return *this;
             bool isOneOf = (... || jsonConvertibleTo(self().m_json.type(), T));
@@ -140,7 +140,7 @@ namespace geode {
             return *this;
         }
 
-        template <json::Type T>
+        template <matjson::Type T>
         JsonMaybeValue& is() {
             if (this->isError()) return *this;
             self().m_hasValue = jsonConvertibleTo(self().m_json.type(), T);
@@ -268,14 +268,14 @@ namespace geode {
         std::set<std::string> m_knownKeys;
 
         JsonMaybeObject(
-            JsonChecker& checker, json::Value& json, std::string const& hierarchy, bool hasValue
+            JsonChecker& checker, matjson::Value& json, std::string const& hierarchy, bool hasValue
         );
 
         JsonMaybeSomething& self();
 
         void addKnownKey(std::string const& key);
 
-        json::Value& json();
+        matjson::Value& json();
 
         JsonMaybeValue emptyValue();
 
@@ -288,9 +288,9 @@ namespace geode {
 
     struct GEODE_DLL JsonChecker {
         std::variant<std::monostate, std::string> m_result;
-        json::Value& m_json;
+        matjson::Value& m_json;
 
-        JsonChecker(json::Value& json);
+        JsonChecker(matjson::Value& json);
 
         bool isError() const;
 
diff --git a/loader/include/Geode/utils/VersionInfo.hpp b/loader/include/Geode/utils/VersionInfo.hpp
index 6756b331..ab49d23a 100644
--- a/loader/include/Geode/utils/VersionInfo.hpp
+++ b/loader/include/Geode/utils/VersionInfo.hpp
@@ -2,7 +2,7 @@
 
 #include "../DefaultInclude.hpp"
 #include <string_view>
-#include <json.hpp>
+#include <matjson.hpp>
 #include <tuple>
 #include "../utils/Result.hpp"
 
@@ -232,15 +232,15 @@ namespace geode {
 
 template <class V>
 requires std::is_same_v<V, geode::VersionInfo> || std::is_same_v<V, geode::ComparableVersionInfo>
-struct json::Serialize<V> {
-    static json::Value to_json(V const& info) {
+struct matjson::Serialize<V> {
+    static matjson::Value to_json(V const& info) {
         return info.toString();
     }
 
-    static V from_json(json::Value const& json) {
+    static V from_json(matjson::Value const& json) {
         auto ver = V::parse(json.as_string());
         if (!ver) {
-            throw json::JsonException(
+            throw matjson::JsonException(
                 "Invalid version format: " + ver.unwrapErr()
             );
         }
diff --git a/loader/include/Geode/utils/cocos.hpp b/loader/include/Geode/utils/cocos.hpp
index edc4fd2e..ca997272 100644
--- a/loader/include/Geode/utils/cocos.hpp
+++ b/loader/include/Geode/utils/cocos.hpp
@@ -1,6 +1,6 @@
 #pragma once
 
-#include <json.hpp>
+#include <matjson.hpp>
 #include "casts.hpp"
 #include "general.hpp"
 #include "../DefaultInclude.hpp"
@@ -13,15 +13,15 @@
 // support converting ccColor3B / ccColor4B to / from json
 
 template <>
-struct json::Serialize<cocos2d::ccColor3B> {
-    static json::Value GEODE_DLL to_json(cocos2d::ccColor3B const& color);
-    static cocos2d::ccColor3B GEODE_DLL from_json(json::Value const& color);
+struct matjson::Serialize<cocos2d::ccColor3B> {
+    static matjson::Value GEODE_DLL to_json(cocos2d::ccColor3B const& color);
+    static cocos2d::ccColor3B GEODE_DLL from_json(matjson::Value const& color);
 };
 
 template <>
-struct json::Serialize<cocos2d::ccColor4B> {
-    static json::Value GEODE_DLL to_json(cocos2d::ccColor4B const& color);
-    static cocos2d::ccColor4B GEODE_DLL from_json(json::Value const& color);
+struct matjson::Serialize<cocos2d::ccColor4B> {
+    static matjson::Value GEODE_DLL to_json(cocos2d::ccColor4B const& color);
+    static cocos2d::ccColor4B GEODE_DLL from_json(matjson::Value const& color);
 };
 
 // operators for CC geometry
diff --git a/loader/include/Geode/utils/file.hpp b/loader/include/Geode/utils/file.hpp
index d5d421d0..d28791fa 100644
--- a/loader/include/Geode/utils/file.hpp
+++ b/loader/include/Geode/utils/file.hpp
@@ -4,25 +4,25 @@
 #include "general.hpp"
 #include "../loader/Event.hpp"
 
-#include <json.hpp>
+#include <matjson.hpp>
 #include <Geode/DefaultInclude.hpp>
 #include <ghc/fs_fwd.hpp>
 #include <string>
 #include <unordered_set>
 
 template <>
-struct json::Serialize<ghc::filesystem::path> {
-    static json::Value to_json(ghc::filesystem::path const& path) {
+struct matjson::Serialize<ghc::filesystem::path> {
+    static matjson::Value to_json(ghc::filesystem::path const& path) {
         return path.string();
     }
-    static ghc::filesystem::path from_json(json::Value const& value) {
+    static ghc::filesystem::path from_json(matjson::Value const& value) {
         return value.as_string();
     }
 };
 
 namespace geode::utils::file {
     GEODE_DLL Result<std::string> readString(ghc::filesystem::path const& path);
-    GEODE_DLL Result<json::Value> readJson(ghc::filesystem::path const& path);
+    GEODE_DLL Result<matjson::Value> readJson(ghc::filesystem::path const& path);
     GEODE_DLL Result<ByteVector> readBinary(ghc::filesystem::path const& path);
 
     template <class T>
@@ -42,7 +42,7 @@ namespace geode::utils::file {
     template <class T>
     Result<> writeToJson(ghc::filesystem::path const& path, T const& data) {
         try {
-            GEODE_UNWRAP(writeString(path, json::Value(data).dump()));
+            GEODE_UNWRAP(writeString(path, matjson::Value(data).dump()));
             return Ok();
         }
         catch(std::exception& e) {
diff --git a/loader/include/Geode/utils/web.hpp b/loader/include/Geode/utils/web.hpp
index b64c63a3..01f950ab 100644
--- a/loader/include/Geode/utils/web.hpp
+++ b/loader/include/Geode/utils/web.hpp
@@ -2,7 +2,7 @@
 
 #include "../DefaultInclude.hpp"
 #include "MiniFunction.hpp"
-#include <json.hpp>
+#include <matjson.hpp>
 #include "Result.hpp"
 #include "general.hpp"
 
@@ -47,7 +47,7 @@ namespace geode::utils::web {
      * @param url URL to fetch
      * @returns Returned data as JSON, or error on error
      */
-    Result<json::Value> fetchJSON(std::string const& url);
+    Result<matjson::Value> fetchJSON(std::string const& url);
 
     class SentAsyncWebRequest;
     template <class T>
@@ -189,7 +189,7 @@ namespace geode::utils::web {
          * `postRequest` or `customRequest` was called before. Additionally
          * sets the content type to application/json.
          */
-        AsyncWebRequest& postFields(json::Value const& fields);
+        AsyncWebRequest& postFields(matjson::Value const& fields);
         /**
          * URL to fetch from the internet asynchronously
          * @param url URL of the data to download. Redirects will be
@@ -316,7 +316,7 @@ namespace geode::utils::web {
          * @returns AsyncWebResult, where you can specify the `then` action for
          * after the download is finished
          */
-        AsyncWebResult<json::Value> json();
+        AsyncWebResult<matjson::Value> json();
 
         /**
          * Download into memory as a custom type. The data will first be
diff --git a/loader/src/hooks/GeodeNodeMetadata.cpp b/loader/src/hooks/GeodeNodeMetadata.cpp
index 346c7d09..5aa45d1a 100644
--- a/loader/src/hooks/GeodeNodeMetadata.cpp
+++ b/loader/src/hooks/GeodeNodeMetadata.cpp
@@ -21,7 +21,7 @@ private:
     std::string m_id = "";
     Ref<Layout> m_layout = nullptr;
     std::unique_ptr<LayoutOptions> m_layoutOptions = nullptr;
-    std::unordered_map<std::string, json::Value> m_attributes;
+    std::unordered_map<std::string, matjson::Value> m_attributes;
     std::unordered_set<std::unique_ptr<EventListenerProtocol>> m_eventListeners;
     std::unordered_map<std::string, std::unique_ptr<EventListenerProtocol>> m_idEventListeners;
 
@@ -166,7 +166,7 @@ void CCNode::updateLayout(bool updateChildOrder) {
     }
 }
 
-AttributeSetEvent::AttributeSetEvent(CCNode* node, std::string const& id, json::Value& value)
+AttributeSetEvent::AttributeSetEvent(CCNode* node, std::string const& id, matjson::Value& value)
   : node(node), id(id), value(value) {}
 
 ListenerResult AttributeSetFilter::handle(MiniFunction<Callback> fn, AttributeSetEvent* event) {
@@ -178,13 +178,13 @@ ListenerResult AttributeSetFilter::handle(MiniFunction<Callback> fn, AttributeSe
 
 AttributeSetFilter::AttributeSetFilter(std::string const& id) : m_targetID(id) {}
 
-void CCNode::setAttribute(std::string const& attr, json::Value const& value) {
+void CCNode::setAttribute(std::string const& attr, matjson::Value const& value) {
     auto meta = GeodeNodeMetadata::set(this);
     meta->m_attributes[attr] = value;
     AttributeSetEvent(this, attr, meta->m_attributes.at(attr)).post();
 }
 
-std::optional<json::Value> CCNode::getAttributeInternal(std::string const& attr) {
+std::optional<matjson::Value> CCNode::getAttributeInternal(std::string const& attr) {
     auto meta = GeodeNodeMetadata::set(this);
     if (meta->m_attributes.count(attr)) {
         return meta->m_attributes.at(attr);
diff --git a/loader/src/load.cpp b/loader/src/load.cpp
index dca175af..85b10a33 100644
--- a/loader/src/load.cpp
+++ b/loader/src/load.cpp
@@ -25,16 +25,16 @@ $execute {
         }
     });
     
-    listenForIPC("ipc-test", [](IPCEvent* event) -> json::Value {
+    listenForIPC("ipc-test", [](IPCEvent* event) -> matjson::Value {
         return "Hello from Geode!";
     });
 
-    listenForIPC("loader-info", [](IPCEvent* event) -> json::Value {
+    listenForIPC("loader-info", [](IPCEvent* event) -> matjson::Value {
         return Mod::get()->getMetadata();
     });
 
-    listenForIPC("list-mods", [](IPCEvent* event) -> json::Value {
-        std::vector<json::Value> res;
+    listenForIPC("list-mods", [](IPCEvent* event) -> matjson::Value {
+        std::vector<matjson::Value> res;
 
         auto args = *event->messageData;
         JsonChecker checker(args);
diff --git a/loader/src/loader/Hook.cpp b/loader/src/loader/Hook.cpp
index c1b42c57..c314f53a 100644
--- a/loader/src/loader/Hook.cpp
+++ b/loader/src/loader/Hook.cpp
@@ -43,7 +43,7 @@ Mod* Hook::getOwner() const {
     return m_impl->getOwner();
 }
 
-json::Value Hook::getRuntimeInfo() const {
+matjson::Value Hook::getRuntimeInfo() const {
     return m_impl->getRuntimeInfo();
 }
 
diff --git a/loader/src/loader/HookImpl.cpp b/loader/src/loader/HookImpl.cpp
index 9f918cfb..49ee5495 100644
--- a/loader/src/loader/HookImpl.cpp
+++ b/loader/src/loader/HookImpl.cpp
@@ -31,8 +31,8 @@ bool Hook::Impl::isEnabled() const {
 Mod* Hook::Impl::getOwner() const {
     return m_owner;
 }
-json::Value Hook::Impl::getRuntimeInfo() const {
-    auto json = json::Object();
+matjson::Value Hook::Impl::getRuntimeInfo() const {
+    auto json = matjson::Object();
     json["address"] = std::to_string(reinterpret_cast<uintptr_t>(m_address));
     json["detour"] = std::to_string(reinterpret_cast<uintptr_t>(m_detour));
     json["name"] = m_displayName;
diff --git a/loader/src/loader/HookImpl.hpp b/loader/src/loader/HookImpl.hpp
index 92538f4c..aa309055 100644
--- a/loader/src/loader/HookImpl.hpp
+++ b/loader/src/loader/HookImpl.hpp
@@ -41,7 +41,7 @@ public:
     std::string_view getDisplayName() const;
     bool isEnabled() const;
     Mod* getOwner() const;
-    json::Value getRuntimeInfo() const;
+    matjson::Value getRuntimeInfo() const;
     tulip::hook::HookMetadata getHookMetadata() const;
     void setHookMetadata(tulip::hook::HookMetadata const& metadata);
     int32_t getPriority() const;
diff --git a/loader/src/loader/IPC.cpp b/loader/src/loader/IPC.cpp
index 7fd01fed..40defb17 100644
--- a/loader/src/loader/IPC.cpp
+++ b/loader/src/loader/IPC.cpp
@@ -1,9 +1,9 @@
 #include <Geode/loader/IPC.hpp>
-#include <json.hpp>
+#include <matjson.hpp>
 
 using namespace geode::prelude;
 
-std::monostate geode::listenForIPC(std::string const& messageID, json::Value(*callback)(IPCEvent*)) {
+std::monostate geode::listenForIPC(std::string const& messageID, matjson::Value(*callback)(IPCEvent*)) {
     (void) new EventListener(
         callback, IPCFilter(getMod()->getID(), messageID)
     );
@@ -14,13 +14,13 @@ IPCEvent::IPCEvent(
     void* rawPipeHandle,
     std::string const& targetModID,
     std::string const& messageID,
-    json::Value const& messageData,
-    json::Value& replyData
+    matjson::Value const& messageData,
+    matjson::Value& replyData
 ) : m_rawPipeHandle(rawPipeHandle),
     targetModID(targetModID),
     messageID(messageID),
     replyData(replyData),
-    messageData(std::make_unique<json::Value>(messageData)) {}
+    messageData(std::make_unique<matjson::Value>(messageData)) {}
 
 IPCEvent::~IPCEvent() {}
 
diff --git a/loader/src/loader/LoaderImpl.cpp b/loader/src/loader/LoaderImpl.cpp
index ac95c223..7364bc89 100644
--- a/loader/src/loader/LoaderImpl.cpp
+++ b/loader/src/loader/LoaderImpl.cpp
@@ -734,7 +734,7 @@ bool Loader::Impl::platformConsoleOpen() const {
 }
 
 void Loader::Impl::fetchLatestGithubRelease(
-    utils::MiniFunction<void(json::Value const&)> then,
+    utils::MiniFunction<void(matjson::Value const&)> then,
     utils::MiniFunction<void(std::string const&)> expect
 ) {
     if (m_latestGithubRelease) {
@@ -746,7 +746,7 @@ void Loader::Impl::fetchLatestGithubRelease(
         .userAgent("github_api/1.0")
         .fetch("https://api.github.com/repos/geode-sdk/geode/releases/latest")
         .json()
-        .then([this, then](json::Value const& json) {
+        .then([this, then](matjson::Value const& json) {
             m_latestGithubRelease = json;
             then(json);
         })
@@ -815,7 +815,7 @@ void Loader::Impl::downloadLoaderResources(bool useLatestRelease) {
             this->getVersion().toString()
         ))
         .json()
-        .then([this](json::Value const& json) {
+        .then([this](matjson::Value const& json) {
             this->tryDownloadLoaderResources(fmt::format(
                 "https://github.com/geode-sdk/geode/releases/download/{}/resources.zip",
                 this->getVersion().toString()
@@ -826,7 +826,7 @@ void Loader::Impl::downloadLoaderResources(bool useLatestRelease) {
                 if (useLatestRelease) {
                     log::debug("Loader version {} does not exist on Github, downloading latest resources", this->getVersion().toString());
                     fetchLatestGithubRelease(
-                        [this](json::Value const& raw) {
+                        [this](matjson::Value const& raw) {
                             auto json = raw;
                             JsonChecker checker(json);
                             auto root = checker.root("[]").obj();
@@ -967,7 +967,7 @@ void Loader::Impl::downloadLoaderUpdate(std::string const& url) {
 void Loader::Impl::checkForLoaderUpdates() {
     // Check for updates in the background
     fetchLatestGithubRelease(
-        [this](json::Value const& raw) {
+        [this](matjson::Value const& raw) {
             auto json = raw;
             JsonChecker checker(json);
             auto root = checker.root("[]").obj();
@@ -1015,12 +1015,12 @@ bool Loader::Impl::isNewUpdateDownloaded() const {
     return m_isNewUpdateDownloaded;
 }
     
-json::Value Loader::Impl::processRawIPC(void* rawHandle, std::string const& buffer) {
-    json::Value reply;
+matjson::Value Loader::Impl::processRawIPC(void* rawHandle, std::string const& buffer) {
+    matjson::Value reply;
 
-    json::Value json;
+    matjson::Value json;
     try {
-        json = json::parse(buffer);
+        json = matjson::parse(buffer);
     } catch (...) {
         log::warn("Received IPC message that isn't valid JSON");
         return reply;
@@ -1034,7 +1034,7 @@ json::Value Loader::Impl::processRawIPC(void* rawHandle, std::string const& buff
         log::warn("Received IPC message without 'message' field");
         return reply;
     }
-    json::Value data;
+    matjson::Value data;
     if (json.contains("data")) {
         data = json["data"];
     }
diff --git a/loader/src/loader/LoaderImpl.hpp b/loader/src/loader/LoaderImpl.hpp
index 87f78b38..e28aef46 100644
--- a/loader/src/loader/LoaderImpl.hpp
+++ b/loader/src/loader/LoaderImpl.hpp
@@ -2,7 +2,7 @@
 
 #include "FileWatcher.hpp"
 
-#include <json.hpp>
+#include <matjson.hpp>
 #include <Geode/loader/Dirs.hpp>
 #include <Geode/loader/Index.hpp>
 #include <Geode/loader/Loader.hpp>
@@ -64,7 +64,7 @@ namespace geode {
 
         // cache for the json of the latest github release to avoid hitting 
         // the github api too much
-        std::optional<json::Value> m_latestGithubRelease;
+        std::optional<matjson::Value> m_latestGithubRelease;
         bool m_isNewUpdateDownloaded = false;
 
         LoadingState m_loadingState;
@@ -107,7 +107,7 @@ namespace geode {
         void downloadLoaderResources(bool useLatestRelease = false);
         void downloadLoaderUpdate(std::string const& url);
         void fetchLatestGithubRelease(
-            utils::MiniFunction<void(json::Value const&)> then,
+            utils::MiniFunction<void(matjson::Value const&)> then,
             utils::MiniFunction<void(std::string const&)> expect
         );
 
@@ -155,7 +155,7 @@ namespace geode {
 
         bool didLastLaunchCrash() const;
 
-        json::Value processRawIPC(void* rawHandle, std::string const& buffer);
+        matjson::Value processRawIPC(void* rawHandle, std::string const& buffer);
 
         void queueInMainThread(ScheduledFunction func);
         void executeGDThreadQueue();
diff --git a/loader/src/loader/Mod.cpp b/loader/src/loader/Mod.cpp
index 672f9fd3..1bd6f3eb 100644
--- a/loader/src/loader/Mod.cpp
+++ b/loader/src/loader/Mod.cpp
@@ -36,7 +36,7 @@ VersionInfo Mod::getVersion() const {
     return m_impl->getVersion();
 }
 
-json::Value& Mod::getSaveContainer() {
+matjson::Value& Mod::getSaveContainer() {
     return m_impl->getSaveContainer();
 }
 
diff --git a/loader/src/loader/ModImpl.cpp b/loader/src/loader/ModImpl.cpp
index c1c083d3..fb7b7529 100644
--- a/loader/src/loader/ModImpl.cpp
+++ b/loader/src/loader/ModImpl.cpp
@@ -108,7 +108,7 @@ VersionInfo Mod::Impl::getVersion() const {
     return m_metadata.getVersion();
 }
 
-json::Value& Mod::Impl::getSaveContainer() {
+matjson::Value& Mod::Impl::getSaveContainer() {
     return m_saved;
 }
 
@@ -146,7 +146,7 @@ Result<> Mod::Impl::loadData() {
         GEODE_UNWRAP_INTO(auto settingData, utils::file::readString(settingPath));
         try {
             // parse settings.json
-            auto json = json::parse(settingData);
+            auto json = matjson::parse(settingData);
 
             JsonChecker checker(json);
             auto root = checker.root("[settings.json]");
@@ -189,13 +189,13 @@ Result<> Mod::Impl::loadData() {
         GEODE_UNWRAP_INTO(auto data, utils::file::readString(savedPath));
 
         try {
-            m_saved = json::parse(data);
+            m_saved = matjson::parse(data);
         } catch (std::exception& err) {
             return Err(std::string("Unable to parse saved values: ") + err.what());
         }
         if (!m_saved.is_object()) {
             log::warn("saved.json was somehow not an object, forcing it to one");
-            m_saved = json::Object();
+            m_saved = matjson::Object();
         }
     }
 
@@ -211,7 +211,7 @@ Result<> Mod::Impl::saveData() {
     std::unordered_set<std::string> coveredSettings;
 
     // Settings
-    json::Value json = json::Object();
+    matjson::Value json = matjson::Object();
     for (auto& [key, value] : m_settings) {
         coveredSettings.insert(key);
         if (!value->save(json[key])) {
@@ -627,12 +627,12 @@ char const* Mod::Impl::expandSpriteName(char const* name) {
 ModJson Mod::Impl::getRuntimeInfo() const {
     auto json = m_metadata.toJSON();
 
-    auto obj = json::Object();
-    obj["hooks"] = json::Array();
+    auto obj = matjson::Object();
+    obj["hooks"] = matjson::Array();
     for (auto hook : m_hooks) {
         obj["hooks"].as_array().push_back(ModJson(hook->getRuntimeInfo()));
     }
-    obj["patches"] = json::Array();
+    obj["patches"] = matjson::Array();
     for (auto patch : m_patches) {
         obj["patches"].as_array().push_back(ModJson(patch->getRuntimeInfo()));
     }
@@ -661,9 +661,9 @@ bool Mod::Impl::shouldLoad() const {
 
 static Result<ModMetadata> getModImplInfo() {
     std::string err;
-    json::Value json;
+    matjson::Value json;
     try {
-        json = json::parse(LOADER_MOD_JSON);
+        json = matjson::parse(LOADER_MOD_JSON);
     } catch (std::exception& err) {
         return Err("Unable to parse mod.json: " + std::string(err.what()));
     }
diff --git a/loader/src/loader/ModImpl.hpp b/loader/src/loader/ModImpl.hpp
index e3aca580..1ca78a4f 100644
--- a/loader/src/loader/ModImpl.hpp
+++ b/loader/src/loader/ModImpl.hpp
@@ -1,6 +1,6 @@
 #pragma once
 
-#include <json.hpp>
+#include <matjson.hpp>
 
 namespace geode {
     class Mod::Impl {
@@ -43,7 +43,7 @@ namespace geode {
         /**
          * Saved values
          */
-        json::Value m_saved = json::Object();
+        matjson::Value m_saved = matjson::Object();
         /**
          * Setting values
          */
@@ -51,7 +51,7 @@ namespace geode {
         /**
          * Settings save data. Stored for efficient loading of custom settings
          */
-        json::Value m_savedSettingsData = json::Object();
+        matjson::Value m_savedSettingsData = matjson::Object();
         /**
          * Whether the mod resources are loaded or not
          */
@@ -94,7 +94,7 @@ namespace geode {
         ghc::filesystem::path getTempDir() const;
         ghc::filesystem::path getBinaryPath() const;
 
-        json::Value& getSaveContainer();
+        matjson::Value& getSaveContainer();
 
 #if defined(GEODE_EXPOSE_SECRET_INTERNALS_IN_HEADERS_DO_NOT_DEFINE_PLEASE)
         void setMetadata(ModMetadata const& metadata);
diff --git a/loader/src/loader/ModMetadataImpl.cpp b/loader/src/loader/ModMetadataImpl.cpp
index e4635aa5..2ad33bd9 100644
--- a/loader/src/loader/ModMetadataImpl.cpp
+++ b/loader/src/loader/ModMetadataImpl.cpp
@@ -4,7 +4,7 @@
 #include <Geode/utils/file.hpp>
 #include <Geode/utils/string.hpp>
 #include <about.hpp>
-#include <json.hpp>
+#include <matjson.hpp>
 #include <utility>
 
 #include "ModMetadataImpl.hpp"
@@ -185,7 +185,7 @@ Result<ModMetadata> ModMetadata::Impl::createFromFile(ghc::filesystem::path cons
     GEODE_UNWRAP_INTO(auto read, utils::file::readString(path));
 
     try {
-        GEODE_UNWRAP_INTO(auto info, ModMetadata::create(json::parse(read)));
+        GEODE_UNWRAP_INTO(auto info, ModMetadata::create(matjson::parse(read)));
 
         auto impl = info.m_impl.get();
 
@@ -219,7 +219,7 @@ Result<ModMetadata> ModMetadata::Impl::createFromGeodeZip(file::Unzip& unzip) {
     std::string err;
     ModJson json;
     try {
-        json = json::parse(std::string(jsonData.begin(), jsonData.end()));
+        json = matjson::parse(std::string(jsonData.begin(), jsonData.end()));
     }
     catch (std::exception& err) {
         return Err(err.what());
@@ -497,8 +497,8 @@ ModMetadata& ModMetadata::operator=(ModMetadata&& other) noexcept {
 ModMetadata::~ModMetadata() = default;
 
 template <>
-struct json::Serialize<geode::ModMetadata::Dependency::Importance> {
-    static json::Value GEODE_DLL to_json(geode::ModMetadata::Dependency::Importance const& importance) {
+struct matjson::Serialize<geode::ModMetadata::Dependency::Importance> {
+    static matjson::Value GEODE_DLL to_json(geode::ModMetadata::Dependency::Importance const& importance) {
         switch (importance) {
             case geode::ModMetadata::Dependency::Importance::Required: return {"required"};
             case geode::ModMetadata::Dependency::Importance::Recommended: return {"recommended"};
@@ -506,7 +506,7 @@ struct json::Serialize<geode::ModMetadata::Dependency::Importance> {
             default: return {"unknown"};
         }
     }
-    static geode::ModMetadata::Dependency::Importance GEODE_DLL from_json(json::Value const& importance) {
+    static geode::ModMetadata::Dependency::Importance GEODE_DLL from_json(matjson::Value const& importance) {
         auto impStr = importance.as_string();
         if (impStr == "required")
             return geode::ModMetadata::Dependency::Importance::Required;
@@ -514,25 +514,25 @@ struct json::Serialize<geode::ModMetadata::Dependency::Importance> {
             return geode::ModMetadata::Dependency::Importance::Recommended;
         if (impStr == "suggested")
             return geode::ModMetadata::Dependency::Importance::Suggested;
-        throw json::JsonException(R"(Expected importance to be "required", "recommended" or "suggested")");
+        throw matjson::JsonException(R"(Expected importance to be "required", "recommended" or "suggested")");
     }
 };
 
 template <>
-struct json::Serialize<geode::ModMetadata::Incompatibility::Importance> {
-    static json::Value GEODE_DLL to_json(geode::ModMetadata::Incompatibility::Importance const& importance) {
+struct matjson::Serialize<geode::ModMetadata::Incompatibility::Importance> {
+    static matjson::Value GEODE_DLL to_json(geode::ModMetadata::Incompatibility::Importance const& importance) {
         switch (importance) {
             case geode::ModMetadata::Incompatibility::Importance::Breaking: return {"breaking"};
             case geode::ModMetadata::Incompatibility::Importance::Conflicting: return {"conflicting"};
             default: return {"unknown"};
         }
     }
-    static geode::ModMetadata::Incompatibility::Importance GEODE_DLL from_json(json::Value const& importance) {
+    static geode::ModMetadata::Incompatibility::Importance GEODE_DLL from_json(matjson::Value const& importance) {
         auto impStr = importance.as_string();
         if (impStr == "breaking")
             return geode::ModMetadata::Incompatibility::Importance::Breaking;
         if (impStr == "conflicting")
             return geode::ModMetadata::Incompatibility::Importance::Conflicting;
-        throw json::JsonException(R"(Expected importance to be "breaking" or "conflicting")");
+        throw matjson::JsonException(R"(Expected importance to be "breaking" or "conflicting")");
     }
 };
diff --git a/loader/src/loader/Patch.cpp b/loader/src/loader/Patch.cpp
index a056396d..c6199ff2 100644
--- a/loader/src/loader/Patch.cpp
+++ b/loader/src/loader/Patch.cpp
@@ -1,5 +1,5 @@
 #include <Geode/loader/Hook.hpp>
-#include <json.hpp>
+#include <matjson.hpp>
 
 using namespace geode::prelude;
 
@@ -42,14 +42,14 @@ Mod* Patch::getOwner() const {
 Patch::~Patch() {}
 
 template <>
-struct json::Serialize<ByteVector> {
-    static json::Value to_json(ByteVector const& bytes) {
-        return json::Array(bytes.begin(), bytes.end());
+struct matjson::Serialize<ByteVector> {
+    static matjson::Value to_json(ByteVector const& bytes) {
+        return matjson::Array(bytes.begin(), bytes.end());
     }
 };
 
-json::Value Patch::getRuntimeInfo() const {
-    auto json = json::Object();
+matjson::Value Patch::getRuntimeInfo() const {
+    auto json = matjson::Object();
     json["address"] = std::to_string(reinterpret_cast<uintptr_t>(m_address));
     json["original"] = m_original;
     json["patch"] = m_patch;
diff --git a/loader/src/loader/Setting.cpp b/loader/src/loader/Setting.cpp
index e5dcda72..e202944b 100644
--- a/loader/src/loader/Setting.cpp
+++ b/loader/src/loader/Setting.cpp
@@ -75,7 +75,7 @@ Result<FileSetting> FileSetting::parse(JsonMaybeObject& obj) {
                 Filter filter;
                 iobj.has("description").into(filter.description);
 
-                std::vector<json::Value> files;
+                std::vector<matjson::Value> files;
                 iobj.has("files").into(files);
 
                 for (auto& i : files) {
diff --git a/loader/src/platform/ios/LoaderImpl.cpp b/loader/src/platform/ios/LoaderImpl.cpp
index c3a599f2..f752c466 100644
--- a/loader/src/platform/ios/LoaderImpl.cpp
+++ b/loader/src/platform/ios/LoaderImpl.cpp
@@ -30,7 +30,7 @@ void Loader::Impl::openPlatformConsole() {
 void Loader::Impl::closePlatformConsole() {}
 
 void Loader::Impl::postIPCReply(
-    void* rawPipeHandle, std::string const& replyID, json::Value const& data
+    void* rawPipeHandle, std::string const& replyID, matjson::Value const& data
 ) {}
 
 void Loader::Impl::setupIPC() {
diff --git a/loader/src/utils/JsonValidation.cpp b/loader/src/utils/JsonValidation.cpp
index 0612a59e..77cc0be0 100644
--- a/loader/src/utils/JsonValidation.cpp
+++ b/loader/src/utils/JsonValidation.cpp
@@ -3,13 +3,13 @@
 using namespace geode::prelude;
 
 
-json::Value& JsonMaybeSomething::json() {
+matjson::Value& JsonMaybeSomething::json() {
     return m_json;
 }
 
 
 JsonMaybeSomething::JsonMaybeSomething(
-    JsonChecker& checker, json::Value& json, std::string const& hierarchy, bool hasValue
+    JsonChecker& checker, matjson::Value& json, std::string const& hierarchy, bool hasValue
 ) :
     m_checker(checker),
     m_json(json), m_hierarchy(hierarchy), m_hasValue(hasValue) {}
@@ -36,7 +36,7 @@ void JsonMaybeSomething::setError(std::string const& error) {
 
 
 JsonMaybeValue::JsonMaybeValue(
-    JsonChecker& checker, json::Value& json, std::string const& hierarchy, bool hasValue
+    JsonChecker& checker, matjson::Value& json, std::string const& hierarchy, bool hasValue
 ) :
     JsonMaybeSomething(checker, json, hierarchy, hasValue) {}
 
@@ -250,7 +250,7 @@ typename JsonMaybeValue::template Iterator<std::pair<std::string, JsonMaybeValue
 
 
 JsonMaybeObject::JsonMaybeObject(
-    JsonChecker& checker, json::Value& json, std::string const& hierarchy, bool hasValue
+    JsonChecker& checker, matjson::Value& json, std::string const& hierarchy, bool hasValue
 ) :
     JsonMaybeSomething(checker, json, hierarchy, hasValue) {}
 
@@ -265,7 +265,7 @@ void JsonMaybeObject::addKnownKey(std::string const& key) {
 }
 
 
-json::Value& JsonMaybeObject::json() {
+matjson::Value& JsonMaybeObject::json() {
     return self().m_json;
 }
 
@@ -305,7 +305,7 @@ void JsonMaybeObject::checkUnknownKeys() {
 }
 
 
-JsonChecker::JsonChecker(json::Value& json) : m_json(json), m_result(std::monostate()) {}
+JsonChecker::JsonChecker(matjson::Value& json) : m_json(json), m_result(std::monostate()) {}
 
 
 bool JsonChecker::isError() const {
diff --git a/loader/src/utils/VersionInfo.cpp b/loader/src/utils/VersionInfo.cpp
index 8f624636..885a1e91 100644
--- a/loader/src/utils/VersionInfo.cpp
+++ b/loader/src/utils/VersionInfo.cpp
@@ -4,7 +4,7 @@
 
 #include <Geode/utils/VersionInfo.hpp>
 #include <Geode/utils/general.hpp>
-#include <json.hpp>
+#include <matjson.hpp>
 
 using namespace geode::prelude;
 
diff --git a/loader/src/utils/cocos.cpp b/loader/src/utils/cocos.cpp
index 61522fef..03abacf3 100644
--- a/loader/src/utils/cocos.cpp
+++ b/loader/src/utils/cocos.cpp
@@ -1,18 +1,18 @@
 #include <Geode/modify/LoadingLayer.hpp>
 #include <Geode/utils/cocos.hpp>
-#include <json.hpp>
+#include <matjson.hpp>
 
 using namespace geode::prelude;
 
-json::Value json::Serialize<ccColor3B>::to_json(ccColor3B const& color) {
-    return json::Object {
+matjson::Value matjson::Serialize<ccColor3B>::to_json(ccColor3B const& color) {
+    return matjson::Object {
         { "r", color.r },
         { "g", color.g },
         { "b", color.b }
     };
 }
 
-ccColor3B json::Serialize<ccColor3B>::from_json(json::Value const& json) {
+ccColor3B matjson::Serialize<ccColor3B>::from_json(matjson::Value const& json) {
     ccColor3B color;
     // array
     if (json.is_array()) {
@@ -22,7 +22,7 @@ ccColor3B json::Serialize<ccColor3B>::from_json(json::Value const& json) {
             color.b = json[2].as_int();
         }
         else {
-            throw json::JsonException("Expected color array to have 3 items");
+            throw matjson::JsonException("Expected color array to have 3 items");
         }
     }
     // object
@@ -38,23 +38,23 @@ ccColor3B json::Serialize<ccColor3B>::from_json(json::Value const& json) {
             str.erase(str.begin());
         }
         if (str.size() > 6) {
-            throw json::JsonException("Hex string for color too long");
+            throw matjson::JsonException("Hex string for color too long");
         }
         auto c = cc3bFromHexString(str);
         if (!c) {
-            throw json::JsonException("Invalid color hex string");
+            throw matjson::JsonException("Invalid color hex string");
         }
         color = c.unwrap();
     }
     // bad
     else {
-        throw json::JsonException("Expected color to be array, object or hex string");
+        throw matjson::JsonException("Expected color to be array, object or hex string");
     }
     return color;
 }
 
-json::Value json::Serialize<ccColor4B>::to_json(ccColor4B const& color) {
-    return json::Object {
+matjson::Value matjson::Serialize<ccColor4B>::to_json(ccColor4B const& color) {
+    return matjson::Object {
         { "r", color.r },
         { "g", color.g },
         { "b", color.b },
@@ -62,7 +62,7 @@ json::Value json::Serialize<ccColor4B>::to_json(ccColor4B const& color) {
     };
 }
 
-ccColor4B json::Serialize<ccColor4B>::from_json(json::Value const& json) {
+ccColor4B matjson::Serialize<ccColor4B>::from_json(matjson::Value const& json) {
     ccColor4B color;
     // array
     if (json.is_array()) {
@@ -73,7 +73,7 @@ ccColor4B json::Serialize<ccColor4B>::from_json(json::Value const& json) {
             color.a = json[3].as_int();
         }
         else {
-            throw json::JsonException("Expected color array to have 4 items");
+            throw matjson::JsonException("Expected color array to have 4 items");
         }
     }
     // object
@@ -90,17 +90,17 @@ ccColor4B json::Serialize<ccColor4B>::from_json(json::Value const& json) {
             str.erase(str.begin());
         }
         if (str.size() > 8) {
-            throw json::JsonException("Hex string for color too long");
+            throw matjson::JsonException("Hex string for color too long");
         }
         auto c = cc4bFromHexString(str);
         if (!c) {
-            throw json::JsonException("Invalid color hex string: " + c.unwrapErr());
+            throw matjson::JsonException("Invalid color hex string: " + c.unwrapErr());
         }
         color = c.unwrap();
     }
     // bad
     else {
-        throw json::JsonException("Expected color to be array, object or hex string");
+        throw matjson::JsonException("Expected color to be array, object or hex string");
     }
     return color;
 }
diff --git a/loader/src/utils/file.cpp b/loader/src/utils/file.cpp
index 6823c50a..f70ac915 100644
--- a/loader/src/utils/file.cpp
+++ b/loader/src/utils/file.cpp
@@ -3,7 +3,7 @@
 #include <Geode/utils/file.hpp>
 #include <Geode/utils/map.hpp>
 #include <Geode/utils/string.hpp>
-#include <json.hpp>
+#include <matjson.hpp>
 #include <fstream>
 #include <mz.h>
 #include <mz_os.h>
@@ -41,12 +41,12 @@ Result<std::string> utils::file::readString(ghc::filesystem::path const& path) {
     return Ok(contents);
 }
 
-Result<json::Value> utils::file::readJson(ghc::filesystem::path const& path) {
+Result<matjson::Value> utils::file::readJson(ghc::filesystem::path const& path) {
     auto str = utils::file::readString(path);
     if (!str)
         return Err(str.unwrapErr());
     try {
-        return Ok(json::parse(str.value()));
+        return Ok(matjson::parse(str.value()));
     }
     catch(std::exception const& e) {
         return Err("Unable to parse JSON: " + std::string(e.what()));
diff --git a/loader/src/utils/web.cpp b/loader/src/utils/web.cpp
index a6e360ed..56daeb4d 100644
--- a/loader/src/utils/web.cpp
+++ b/loader/src/utils/web.cpp
@@ -2,7 +2,7 @@
 #include <Geode/loader/Loader.hpp>
 #include <Geode/utils/casts.hpp>
 #include <Geode/utils/web.hpp>
-#include <json.hpp>
+#include <matjson.hpp>
 #include <thread>
 
 using namespace geode::prelude;
@@ -97,11 +97,11 @@ Result<ByteVector> web::fetchBytes(std::string const& url) {
     return Err("Error getting info: " + std::string(curl_easy_strerror(res)));
 }
 
-Result<json::Value> web::fetchJSON(std::string const& url) {
+Result<matjson::Value> web::fetchJSON(std::string const& url) {
     std::string res;
     GEODE_UNWRAP_INTO(res, fetch(url));
     try {
-        return Ok(json::parse(res));
+        return Ok(matjson::parse(res));
     }
     catch (std::exception& e) {
         return Err(e.what());
@@ -482,7 +482,7 @@ AsyncWebRequest& AsyncWebRequest::postFields(std::string const& fields) {
     return *this;
 }
 
-AsyncWebRequest& AsyncWebRequest::postFields(json::Value const& fields) {
+AsyncWebRequest& AsyncWebRequest::postFields(matjson::Value const& fields) {
     this->extra().m_isJsonRequest = true;
     return this->postFields(fields.dump());
 }
@@ -587,10 +587,10 @@ AsyncWebResult<ByteVector> AsyncWebResponse::bytes() {
     });
 }
 
-AsyncWebResult<json::Value> AsyncWebResponse::json() {
-    return this->as(+[](ByteVector const& bytes) -> Result<json::Value> {
+AsyncWebResult<matjson::Value> AsyncWebResponse::json() {
+    return this->as(+[](ByteVector const& bytes) -> Result<matjson::Value> {
         try {
-            return Ok(json::parse(std::string(bytes.begin(), bytes.end())));
+            return Ok(matjson::parse(std::string(bytes.begin(), bytes.end())));
         }
         catch (std::exception& e) {
             return Err(std::string(e.what()));
diff --git a/loader/test/dependency/main.cpp b/loader/test/dependency/main.cpp
index 2f6bd35d..637016b5 100644
--- a/loader/test/dependency/main.cpp
+++ b/loader/test/dependency/main.cpp
@@ -39,7 +39,7 @@ public:
     MySettingValue(std::string const& key, std::string const& modID, Icon icon)
       : SettingValue(key, modID), m_icon(icon) {}
 
-    bool load(json::Value const& json) override {
+    bool load(matjson::Value const& json) override {
         try {
             m_icon = static_cast<Icon>(json.as<int>());
             return true;
@@ -47,7 +47,7 @@ public:
             return false;
         }
     }
-    bool save(json::Value& json) const override {
+    bool save(matjson::Value& json) const override {
         json = static_cast<int>(m_icon);
         return true;
     }