Skip to content

# 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 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:

    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:

    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:

    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:

    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:

    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:

    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:

    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:

    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):

    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:

    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:

    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 - Full JSON Pointer documentation
- JSON Patch - RFC 6902 JSON Patch for `glz::generic`
- Generic JSON - Working with dynamic JSON