File: partial-write.md

package info (click to toggle)
glaze 6.4.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 7,312 kB
  • sloc: cpp: 109,539; sh: 99; ansic: 26; makefile: 13
file content (348 lines) | stat: -rw-r--r-- 9,534 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
# 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<partial>(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<std::string> 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<std::string_view> 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::string>
std::vector<std::string> keys1 = {"x", "name"};

// std::vector<std::string_view>
std::vector<std::string_view> keys2 = {"x", "name"};

// std::array
std::array<std::string_view, 2> keys3 = {"x", "name"};
```

### Error Handling

If a key doesn't exist in the struct, `error_code::unknown_key` is returned:

```c++
std::vector<std::string> 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<std::string> 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<std::string> 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<std::string> keys = {"x", "name"};
glz::write_json_partial<glz::opts{.prettify = true}>(obj, keys, buffer);
// Result:
// {
//    "x": 10,
//    "name": "example"
// }
```

### Return Types

Three overloads are available:

```c++
// 1. Write to resizable buffer (std::string, std::vector<char>)
error_ctx write_json_partial(T&& value, const Keys& keys, Buffer&& buffer);

// 2. Write to raw buffer (char*)
expected<size_t, error_ctx> write_json_partial(T&& value, const Keys& keys, Buffer&& buffer);

// 3. Return a new string
expected<std::string, error_ctx> 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<std::string> 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<std::string> 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<std::string> 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::string>
std::vector<std::string> exclude1 = {"password", "internal_id"};

// std::vector<std::string_view>
std::vector<std::string_view> exclude2 = {"password", "internal_id"};

// std::array
std::array<std::string_view, 2> 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<std::string> 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<std::string> 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<std::string> 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<std::string> 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<std::string> exclude = {"password"};
glz::write_json_exclude<glz::opts{.prettify = true}>(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<char>)
error_ctx write_json_exclude(T&& value, const Keys& exclude_keys, Buffer&& buffer);

// 2. Write to raw buffer (char*)
expected<size_t, error_ctx> write_json_exclude(T&& value, const Keys& exclude_keys, Buffer&& buffer);

// 3. Return a new string
expected<std::string, error_ctx> 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<std::string> 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<partial>` | `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