# Partial Write Glaze supports partial object writing, allowing you to serialize only specific fields. There are three approaches: 1. **Compile-time partial write** - Uses JSON pointers as template parameters (zero runtime overhead) 2. **Runtime partial write (whitelist)** - Specify keys to include at runtime 3. **Runtime exclude write (blacklist)** - Specify keys to exclude at runtime ## Compile-Time Partial Write Use `glz::json_ptrs` to specify JSON pointer paths at compile time. This approach supports nested paths and has zero runtime overhead. ```c++ struct animals_t { std::string lion = "Lion"; std::string tiger = "Tiger"; std::string panda = "Panda"; struct glaze { using T = animals_t; static constexpr auto value = glz::object(&T::lion, &T::tiger, &T::panda); }; }; struct zoo_t { animals_t animals{}; std::string name{"My Awesome Zoo"}; struct glaze { using T = zoo_t; static constexpr auto value = glz::object(&T::animals, &T::name); }; }; "partial write"_test = [] { static constexpr auto partial = glz::json_ptrs("/name", "/animals/tiger"); zoo_t obj{}; std::string s{}; const auto ec = glz::write_json(obj, s); expect(!ec); expect(s == R"({"animals":{"tiger":"Tiger"},"name":"My Awesome Zoo"})") << s; }; ``` ## Runtime Partial Write Use `glz::write_json_partial` to specify keys dynamically at runtime. This is useful when the set of keys to serialize is determined at runtime (e.g., based on user input, configuration, or message type). ### Basic Usage ```c++ struct my_struct { int x = 10; std::string name = "example"; double value = 3.14; bool active = true; }; my_struct obj{}; std::string buffer; // Specify keys at runtime std::vector keys = {"name", "x"}; auto ec = glz::write_json_partial(obj, keys, buffer); // Result: {"name":"example","x":10} ``` ### Key Order The output key order matches the order of keys in your input container: ```c++ std::vector keys = {"value", "name", "x"}; glz::write_json_partial(obj, keys, buffer); // Result: {"value":3.14,"name":"example","x":10} ``` ### Supported Key Containers Any range of string-like types works: ```c++ // std::vector std::vector keys1 = {"x", "name"}; // std::vector std::vector keys2 = {"x", "name"}; // std::array std::array keys3 = {"x", "name"}; ``` ### Error Handling If a key doesn't exist in the struct, `error_code::unknown_key` is returned: ```c++ std::vector keys = {"x", "nonexistent"}; auto ec = glz::write_json_partial(obj, keys, buffer); if (ec.ec == glz::error_code::unknown_key) { // Handle unknown key error } ``` ### Empty Keys An empty key container produces an empty JSON object: ```c++ std::vector keys = {}; glz::write_json_partial(obj, keys, buffer); // Result: {} ``` ### Duplicate Keys Duplicate keys are allowed and will write the field multiple times: ```c++ std::vector keys = {"x", "x"}; glz::write_json_partial(obj, keys, buffer); // Result: {"x":10,"x":10} ``` ### Options Support Runtime partial write supports standard Glaze options like `prettify`: ```c++ std::vector keys = {"x", "name"}; glz::write_json_partial(obj, keys, buffer); // Result: // { // "x": 10, // "name": "example" // } ``` ### Return Types Three overloads are available: ```c++ // 1. Write to resizable buffer (std::string, std::vector) error_ctx write_json_partial(T&& value, const Keys& keys, Buffer&& buffer); // 2. Write to raw buffer (char*) expected write_json_partial(T&& value, const Keys& keys, Buffer&& buffer); // 3. Return a new string expected write_json_partial(T&& value, const Keys& keys); ``` ### Works with Reflectable Types Runtime partial write works with both explicit Glaze metadata and pure reflection (C++ aggregates): ```c++ // No glz::meta needed - pure reflection struct reflectable_struct { int field1 = 100; std::string field2 = "test"; }; reflectable_struct obj{}; std::vector keys = {"field2"}; glz::write_json_partial(obj, keys, buffer); // Result: {"field2":"test"} ``` ## Runtime Exclude Write (Blacklist) Use `glz::write_json_exclude` to specify keys to **exclude** at runtime. This is useful when you want to serialize most fields but omit a few (e.g., sensitive data like passwords, internal IDs, or deprecated fields). ### Basic Usage ```c++ struct my_struct { int x = 10; std::string name = "example"; double value = 3.14; bool active = true; std::string password = "secret"; // Don't serialize this! }; my_struct obj{}; std::string buffer; // Exclude specific keys at runtime std::vector exclude = {"password"}; auto ec = glz::write_json_exclude(obj, exclude, buffer); // Result: {"x":10,"name":"example","value":3.14,"active":true} ``` ### Key Order The output key order matches the struct definition order (not the exclude list order): ```c++ std::vector exclude = {"name"}; glz::write_json_exclude(obj, exclude, buffer); // Result: {"x":10,"value":3.14,"active":true,"password":"secret"} // Keys appear in struct order: x, value, active, password (name excluded) ``` ### Supported Key Containers Any range of string-like types works: ```c++ // std::vector std::vector exclude1 = {"password", "internal_id"}; // std::vector std::vector exclude2 = {"password", "internal_id"}; // std::array std::array exclude3 = {"password", "internal_id"}; ``` ### Error Handling If an exclude key doesn't exist in the struct, `error_code::unknown_key` is returned: ```c++ std::vector exclude = {"nonexistent"}; auto ec = glz::write_json_exclude(obj, exclude, buffer); if (ec.ec == glz::error_code::unknown_key) { // Handle unknown key error } ``` ### Empty Exclude List An empty exclude list writes all fields (equivalent to regular `write_json`): ```c++ std::vector exclude = {}; glz::write_json_exclude(obj, exclude, buffer); // Result: {"x":10,"name":"example","value":3.14,"active":true,"password":"secret"} ``` ### Excluding All Keys Excluding all keys produces an empty JSON object: ```c++ std::vector exclude = {"x", "name", "value", "active", "password"}; glz::write_json_exclude(obj, exclude, buffer); // Result: {} ``` ### Duplicate Exclude Keys Duplicate exclude keys are handled gracefully (the key is just excluded once): ```c++ std::vector exclude = {"password", "password"}; glz::write_json_exclude(obj, exclude, buffer); // Result: {"x":10,"name":"example","value":3.14,"active":true} ``` ### Options Support Runtime exclude write supports standard Glaze options like `prettify`: ```c++ std::vector exclude = {"password"}; glz::write_json_exclude(obj, exclude, buffer); // Result: // { // "x": 10, // "name": "example", // "value": 3.14, // "active": true // } ``` ### Return Types Three overloads are available: ```c++ // 1. Write to resizable buffer (std::string, std::vector) error_ctx write_json_exclude(T&& value, const Keys& exclude_keys, Buffer&& buffer); // 2. Write to raw buffer (char*) expected write_json_exclude(T&& value, const Keys& exclude_keys, Buffer&& buffer); // 3. Return a new string expected write_json_exclude(T&& value, const Keys& exclude_keys); ``` ### Works with Reflectable Types Runtime exclude write works with both explicit Glaze metadata and pure reflection (C++ aggregates): ```c++ // No glz::meta needed - pure reflection struct reflectable_struct { int field1 = 100; std::string field2 = "test"; std::string internal = "hidden"; }; reflectable_struct obj{}; std::vector exclude = {"internal"}; glz::write_json_exclude(obj, exclude, buffer); // Result: {"field1":100,"field2":"test"} ``` ## Choosing Between Approaches | Feature | Compile-Time | Runtime Partial (Whitelist) | Runtime Exclude (Blacklist) | |---------|--------------|-----------------------------|-----------------------------| | Function | `write_json` | `write_json_partial` | `write_json_exclude` | | Key specification | `constexpr` JSON pointers | Runtime container | Runtime container | | Nested paths | Supported | Top-level keys only | Top-level keys only | | Performance | Zero overhead | Hash lookup per key | Hash lookup per exclude key | | Output order | Specified order | Input container order | Struct definition order | | Use case | Fixed field sets | Include specific fields | Exclude specific fields | Use **compile-time partial write** when: - The fields to serialize are known at compile time - You need nested JSON pointer paths - Maximum performance is critical Use **runtime partial write (whitelist)** when: - The fields to serialize depend on runtime conditions - Different message types need different field subsets - User configuration determines which fields to include - You want control over the output key order Use **runtime exclude write (blacklist)** when: - You want to serialize most fields but exclude a few - Excluding sensitive fields (passwords, tokens, internal IDs) - The set of excluded fields is smaller than the set of included fields - You want keys in struct definition order