File: struct-json-pointer.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 (264 lines) | stat: -rw-r--r-- 6,010 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
# JSON Pointer Operations for Structs

Glaze provides JSON Pointer (RFC 6901) operations that work directly with C++ structs and typed data. These operations provide patch-like functionality at compile time with full type safety.

> For runtime JSON manipulation with full RFC 6902 JSON Patch support, see [JSON Patch](./json-patch.md) which works with `glz::generic`.

## Overview

| Operation | Description | Struct Support |
|-----------|-------------|----------------|
| `glz::get` | Read a value at a path | Yes |
| `glz::set` | Write a value at a path | Yes |
| `glz::seek` | Call a function on a value at a path | Yes |
| `glz::read_as_json` | Parse JSON into a specific path | Yes |
| `glz::write_at` | Write raw JSON at a specific path | Yes |

## get - Read Values

### get (reference)

Returns a reference wrapper to the value at the specified path:

```c++
struct Person {
   std::string name;
   int age;
};

Person p{"Alice", 30};

auto name = glz::get<std::string>(p, "/name");
if (name) {
   // name->get() == "Alice"
   name->get() = "Bob";  // Can modify through reference
}

auto age = glz::get<int>(p, "/age");
if (age) {
   // age->get() == 30
}
```

### get_if (pointer)

Returns a pointer to the value, or `nullptr` if not found or wrong type:

```c++
Person p{"Alice", 30};

if (auto* name = glz::get_if<std::string>(p, "/name")) {
   // *name == "Alice"
}

// Returns nullptr for wrong type
auto* wrong = glz::get_if<int>(p, "/name");  // nullptr
```

### get_value (copy)

Returns a copy of the value:

```c++
Person p{"Alice", 30};

auto age = glz::get_value<int>(p, "/age");
if (age) {
   // *age == 30 (copy, not reference)
}
```

## set - Write Values

Assigns a value at the specified path:

```c++
struct Config {
   int timeout;
   std::string host;
   struct {
      int port;
      bool ssl;
   } server;
};

Config cfg{30, "localhost", {8080, false}};

glz::set(cfg, "/timeout", 60);
glz::set(cfg, "/host", std::string("example.com"));
glz::set(cfg, "/server/port", 443);
glz::set(cfg, "/server/ssl", true);
```

`set` returns `true` if the assignment succeeded, `false` if the path doesn't exist or types are incompatible.

## seek - Generic Access

Calls a lambda on the value at the specified path. Useful when you don't know the type at compile time:

```c++
struct Data {
   int x;
   double y;
   std::string z;
};

Data d{1, 2.5, "hello"};

std::any result;
glz::seek([&](auto& value) {
   result = value;
}, d, "/y");
// result contains 2.5
```

## Nested Structures

All operations work with arbitrarily nested structures:

```c++
struct Inner {
   int value;
};

struct Middle {
   Inner inner;
   std::vector<int> items;
};

struct Outer {
   Middle middle;
   std::map<std::string, int> scores;
};

Outer obj{{{{42}, {1, 2, 3}}, {{"math", 95}}}};

// Access nested struct
auto val = glz::get<int>(obj, "/middle/inner/value");  // 42

// Access vector element
auto item = glz::get<int>(obj, "/middle/items/1");  // 2

// Access map value
auto score = glz::get<int>(obj, "/scores/math");  // 95

// Set nested values
glz::set(obj, "/middle/inner/value", 100);
glz::set(obj, "/middle/items/0", 10);
```

## Working with JSON Buffers

### read_as_json

Parse JSON directly into a specific path within a struct:

```c++
struct Scene {
   struct {
      double x, y, z;
   } position;
   std::string name;
};

Scene scene{};

// Parse JSON into a specific location
glz::read_as_json(scene, "/position", R"({"x": 1.0, "y": 2.0, "z": 3.0})");
glz::read_as_json(scene, "/name", R"("Main Camera")");
```

### get_as_json

Extract a typed value from a JSON buffer at a specific path:

```c++
std::string json = R"({"user": {"name": "Alice", "age": 30}})";

auto name = glz::get_as_json<std::string, "/user/name">(json);
// name == "Alice"

auto age = glz::get_as_json<int, "/user/age">(json);
// age == 30
```

### get_sv_json

Get a `std::string_view` to the raw JSON at a path (no parsing):

```c++
std::string json = R"({"data": {"values": [1, 2, 3]}})";

auto view = glz::get_sv_json<"/data/values">(json);
// view == "[1, 2, 3]"
```

### write_at

Replace JSON at a specific path within a buffer:

```c++
std::string json = R"({"action": "pending", "count": 0})";

glz::write_at<"/action">(R"("complete")", json);
glz::write_at<"/count">("42", json);
// json == {"action": "complete", "count": 42}
```

## Comparison with JSON Patch

| Feature | Struct Operations | JSON Patch (glz::generic) |
|---------|------------------|---------------------------|
| Type safety | Compile-time | Runtime |
| Add new keys | No (struct is fixed) | Yes |
| Remove keys | No (struct is fixed) | Yes |
| Replace values | Yes (`glz::set`) | Yes |
| Move/Copy | No | Yes |
| Test operation | No | Yes |
| Batch operations | Manual loop | Atomic transaction |

### When to Use Each

**Use struct operations when:**
- You have a known schema at compile time
- You need maximum performance
- Type safety is important
- Structure is fixed (no dynamic keys)

**Use JSON Patch (`glz::generic`) when:**
- Schema is unknown or dynamic
- You need full RFC 6902 compliance
- You need to add/remove keys at runtime
- You're processing patches from external sources
- You need atomic batch operations with rollback

## Error Handling

Most operations return `expected` or `bool` to indicate success:

```c++
struct Data { int x; };
Data d{42};

// Path doesn't exist
auto result = glz::get<int>(d, "/nonexistent");
if (!result) {
   // result.error().ec == glz::error_code::nonexistent_json_ptr
}

// Wrong type
auto wrong = glz::get<std::string>(d, "/x");
if (!wrong) {
   // wrong.error().ec == glz::error_code::get_wrong_type
}

// set returns bool
bool ok = glz::set(d, "/x", 100);  // true
bool fail = glz::set(d, "/y", 0);  // false (path doesn't exist)
```

## See Also

- [JSON Pointer Syntax](./json-pointer-syntax.md) - Full JSON Pointer documentation
- [JSON Patch](./json-patch.md) - RFC 6902 JSON Patch for `glz::generic`
- [Generic JSON](./generic-json.md) - Working with dynamic JSON