Skip to content

Releases: stephenberry/glaze

v6.5.1

03 Jan 19:19

Choose a tag to compare

Security Enhancements

BEVE/CBOR DoS Protection (#2194)

Binary formats like BEVE and CBOR encode length headers indicating how many elements follow. Previously, a malicious actor could craft a message claiming billions of elements but containing minimal data, causing memory exhaustion before validation.

Glaze now validates length headers against remaining buffer size before any memory allocation:

// Malicious buffer claiming 1 billion strings but containing only a few bytes
std::vector<std::string> result;
auto ec = glz::read_beve(result, malicious_buffer);
// ec.ec == glz::error_code::invalid_length
// No memory was allocated - attack prevented

Protection applies to strings, typed arrays, generic arrays, and maps/objects.

User-Configurable Allocation Limits (#2195)

New compile-time options for stricter memory control:

struct secure_opts : glz::opts
{
   uint32_t format = glz::BEVE;
   size_t max_string_length = 1024;    // Max 1KB per string
   size_t max_array_size = 10000;      // Max 10,000 elements per array
   size_t max_map_size = 1000;         // Max 1,000 entries per map
};

auto ec = glz::read<secure_opts{}>(obj, buffer);

New glz::max_length wrapper for per-field limits:

template <>
struct glz::meta<UserInput>
{
   using T = UserInput;
   static constexpr auto value = object(
      "username", glz::max_length<&T::username, 64>,  // Max 64 chars
      "scores", glz::max_length<&T::scores, 100>      // Max 100 elements
   );
};

See Security Documentation for best practices.

New Features

Bounded Buffer Overflow Detection (#2189)

Writing to fixed-size buffers (like std::array or std::span) now returns error_code::buffer_overflow instead of undefined behavior when capacity is exceeded:

std::array<char, 32> buffer{};
auto ec = glz::write_json(large_object, buffer);
if (ec.ec == glz::error_code::buffer_overflow) {
   // Handle insufficient buffer space
}

allocate_raw_pointers Option (#2196)

New compile-time option to allow allocating memory for null raw pointers during deserialization:

struct alloc_opts : glz::opts {
   bool allocate_raw_pointers = true;
};

std::vector<MyStruct*> vec;
auto ec = glz::read<alloc_opts{}>(vec, json);
// vec now contains allocated pointers - caller must delete them

By default, Glaze refuses to allocate raw pointers to prevent memory leaks. See Nullable Types for details.

Compatibility

iOS Support for Older Versions (#2197)

Added compatibility guards for std::to_chars/std::from_chars floating-point support, which is unavailable on iOS < 16.3. This affects only float128_t serialization; regular float and double types use Glaze's built-in implementation and work on all iOS versions.

Build

  • Removed old Boost::system linkage (#2193)

Full Changelog: v6.5.0...v6.5.1

v6.5.0

01 Jan 20:02

Choose a tag to compare

Streaming I/O support, TOML datetime types, and binary size optimization options.

Streaming I/O

Glaze now supports streaming serialization and deserialization for processing large data with bounded memory usage. This enables reading/writing files of arbitrary size without loading everything into memory.

Output Streaming

Write directly to files or output streams with incremental flushing using basic_ostream_buffer:

#include "glaze/core/ostream_buffer.hpp"

std::ofstream file("output.json");
glz::basic_ostream_buffer<std::ofstream> buffer(file);
auto ec = glz::write_json(obj, buffer);
if (ec || !file.good()) {
    // Handle error
}

// Or use the polymorphic alias for any std::ostream
glz::ostream_buffer<> buffer2(any_ostream);
glz::write_json(obj, buffer2);

Input Streaming

Read directly from files or input streams with automatic refilling using basic_istream_buffer:

#include "glaze/core/istream_buffer.hpp"

std::ifstream file("input.json");
glz::basic_istream_buffer<std::ifstream> buffer(file);
my_struct obj;
auto ec = glz::read_json(obj, buffer);

JSON/NDJSON Stream Reader

Process streams of JSON objects one at a time with json_stream_reader:

#include "glaze/json/json_stream.hpp"

struct Event {
    int id;
    std::string type;
};

std::ifstream file("events.ndjson");
glz::json_stream_reader<Event> reader(file);
Event event;
while (!reader.read_next(event)) {
    process(event);
}

// Or use range-based for loop
for (auto&& event : glz::json_stream_reader<Event>(file)) {
    process(event);
}

TOML Datetime and Set Support

TOML now supports all four datetime formats from the TOML v1.1.0 specification, plus set-like containers. #2186

Supported datetime types:

TOML Type C++ Type
Offset Date-Time std::chrono::system_clock::time_point
Local Date-Time std::chrono::system_clock::time_point
Local Date std::chrono::year_month_day
Local Time std::chrono::hh_mm_ss<Duration>
struct Config {
    std::chrono::year_month_day date;  // TOML: date = 2024-06-15
    std::chrono::hh_mm_ss<std::chrono::milliseconds> time;  // TOML: time = 10:30:45.123
    std::chrono::system_clock::time_point timestamp;  // TOML: timestamp = 2024-06-15T10:30:45Z
    std::set<std::string> tags;  // TOML: tags = ["a", "b", "c"]
};

Binary Size Optimization Options

Two new options help reduce binary size and compilation time for embedded systems and size-constrained environments. #2188

linear_search Option

Uses linear key search instead of hash-based lookup for JSON object fields. This eliminates 256-byte hash tables per struct type, significantly reducing binary size. Faster for small structs (< ~8 fields) due to cache effects.

struct small_binary_opts : glz::opts
{
   bool linear_search = true;
};

glz::read<small_binary_opts>(obj, json);

glaze_DISABLE_ALWAYS_INLINE CMake Option

Disables aggressive inlining during compilation for smaller binaries and faster build times at the cost of runtime performance:

set(glaze_DISABLE_ALWAYS_INLINE ON)

Full Changelog: v6.4.1...v6.5.0

v6.4.1

29 Dec 23:34

Choose a tag to compare

New formatting controls, TOML enum support, extended binary format validation, and SSL/TLS networking improvements.

Features

Float Formatting Control

New float_format option provides flexible control over floating-point precision in JSON output using C++23 std::format specifiers.

Global Option:

struct my_opts : glz::opts {
   static constexpr std::string_view float_format = "{:.2f}";
};

double pi = 3.14159265358979;
glz::write<my_opts{}>(pi); // "3.14"

Per-Member Wrapper:

template <>
struct glz::meta<my_type> {
   using T = my_type;
   static constexpr auto value = glz::object(
      "lat", glz::float_format<&T::latitude, "{:.4f}">,
      "lon", glz::float_format<&T::longitude, "{:.4f}">
   );
};

#2179

TOML Enum Support

Adds enum serialization and deserialization for TOML format, matching existing JSON enum functionality.

enum class Status { Pending, Active, Completed };

template <>
struct glz::meta<Status> {
   using enum Status;
   static constexpr auto value = glz::enumerate(Pending, Active, Completed);
};

Status s = Status::Active;
auto toml = glz::write_toml(s);  // Returns: "Active"

Status parsed;
glz::read_toml(parsed, R"("Completed")");  // parsed == Status::Completed

#2181

error_on_missing_keys for BEVE and MessagePack

The error_on_missing_keys option now works with BEVE and MessagePack formats, not just JSON. When enabled, deserialization fails with a missing_key error if required fields are absent. Optional/nullable fields (std::optional, std::unique_ptr) are still allowed to be missing.

#2184

SSL WebSocket and HTTPS Streaming Support

SSL/TLS support for WebSockets (WSS) and HTTPS streaming.

Key Features:

  • WSS server support for secure WebSocket connections
  • HTTPS streaming with streaming_connection_interface type erasure
  • websocket_connection_interface for socket-type agnostic handlers
  • SSL verify mode configuration for WebSocket clients
  • ASIO 1.32+ compatibility fix for SSL streams
websocket_client client;
client.set_ssl_verify_mode(asio::ssl::verify_none);  // For self-signed certs
client.connect("wss://localhost:8443/ws");

#2165

Improvements

  • API Consistency: Added glz::read_beve_untagged to match write_beve_untagged naming convention. read_binary_untagged is now deprecated. #2178
  • GLIBCXX_USE_CXX11_ABI=0 Support: Glaze can now be used and tested with the legacy GCC ABI. #2160
  • MessagePack Fuzz Testing: Added fuzz testing for MessagePack format. #2159

Bug Fixes

  • Tagged Variant with Empty Structs: Fixed roundtrip failure for tagged variants containing empty struct types. #2180
  • BEVE std::array<bool, N> Compilation: Fixed constexpr compilation error when serializing std::array<bool, N> with BEVE format. #2177
  • Invalid Control Code Parsing: Fixed parsing of strings containing invalid control character sequences. #2169
  • BEVE Skip Logic: Fixed bug where boolean and string typed arrays were handled incorrectly when skipping unknown keys in BEVE format. #2184

Full Changelog: v6.4.0...v6.4.1

v6.4.0

19 Dec 02:01

Choose a tag to compare

CBOR, MessagePack, generic_i64, generic_u64

This release adds support for CBOR and MessagePack along with enhanced runtime JSON manipulation capabilities and new generic JSON integer types.

New Formats

CBOR (Concise Binary Object Representation)

Glaze now provides comprehensive support for CBOR (RFC 8949). CBOR is an IETF standard that enables excellent interoperability with other languages and systems. #2145

#include "glaze/cbor.hpp"

my_struct s{};
std::string buffer{};
glz::write_cbor(s, buffer);

my_struct result{};
glz::read_cbor(result, buffer);

Key Features:

  • RFC 8949 compliance - Core CBOR specification support
  • RFC 8746 typed arrays - Bulk memory operations for contiguous numeric containers (vectors, arrays)
  • Multi-dimensional arrays - Row-major (tag 40) and column-major (tag 1040) support
  • Eigen matrix support - Native serialization of fixed and dynamic Eigen matrices
  • Complex numbers - IANA-registered tags (43000, 43001) for single and array complex types
  • Floating-point preferred serialization - Automatically uses the smallest representation (half/single/double)
  • Exceptions API - glz::ex::write_cbor / glz::ex::read_cbor for exception-based error handling
  • Fuzz tested - Comprehensive fuzzing for robustness #2149

MessagePack

MessagePack support. #2015

#include "glaze/msgpack.hpp"

my_struct s{};
std::string buffer{};
glz::write_msgpack(s, buffer);

my_struct result{};
glz::read_msgpack(result, buffer);

Key Features:

  • Spec 2.0 compliance - Core types, extension types, and timestamp extension
  • Timestamp extension - Type -1 per the MessagePack spec with all three formats (32, 64, 96 bit)
  • std::chrono::system_clock::time_point integration
  • glz::msgpack::ext - Direct handling of MessagePack extension values
  • Binary buffers - Compact bin* tags for std::vector<std::byte> and similar types
  • Partial read/write - JSON pointer support for selective serialization
  • File helpers - glz::write_file_msgpack / glz::read_file_msgpack
  • Options support - Works with standard Glaze options

To use the new formats, include the appropriate headers:

  • CBOR: #include "glaze/cbor.hpp"
  • MessagePack: #include "glaze/msgpack.hpp"

Generic JSON Integer Types

New generic JSON types preserve integer precision beyond the 2^53 limit of double. #2057

Type Number Storage Use Case
glz::generic double Fast, JavaScript-compatible (default)
glz::generic_i64 int64_t then double Signed integer precision up to 2^63-1
glz::generic_u64 uint64_t then int64_t then double Full unsigned 64-bit range
glz::generic_u64 json{};
std::string buffer = R"({"big_id": 18446744073709551615})";
glz::read_json(json, buffer);

// Maximum uint64_t preserved exactly
assert(json["big_id"].get<uint64_t>() == 18446744073709551615ULL);

Runtime JSON Manipulation

Runtime JSON Pointer Support

JSON pointer paths can now be defined at runtime. #2150

std::string buffer = R"({"action":"DELETE","data":{"x":10}})";
std::string path = "/action";
auto ec = glz::write_at(path, R"("GO!")", buffer);
// Result: {"action":"GO!","data":{"x":10}}

Runtime Partial Write (write_json_partial)

Specify which fields to serialize at runtime using a whitelist approach. #2153

my_struct obj{};
std::vector<std::string> keys = {"name", "x"};
std::string buffer;
glz::write_json_partial(obj, keys, buffer);
// Only "name" and "x" fields are serialized

Features:

  • Output key order matches input container order
  • Works with std::vector<std::string>, std::vector<std::string_view>, std::array, etc.
  • Supports standard Glaze options like prettify

Runtime Exclude Write (write_json_exclude)

Specify which fields to exclude at runtime using a blacklist approach. #2154

my_struct obj{};
std::vector<std::string> exclude = {"password", "internal_id"};
std::string buffer;
glz::write_json_exclude(obj, exclude, buffer);
// All fields except "password" and "internal_id" are serialized

Networking Improvements

Templated HTTP Router

basic_http_router is now templated for custom handler types. #2151

// Use custom handler types with the HTTP router
glz::basic_http_router<MyCustomHandler> router;

Additional Improvements

  • raw option support for time_point - Serialize time points as raw integer values #2147
  • Documentation improvements - Added simple_enum callout and updated documentation website links

Fixes

  • Fixed raw and raw_string combined options - Correct behavior when both options are specified #2148
  • MSVC compatibility fix - Resolved build issues on MSVC #2158

Full Changelog: v6.3.0...v6.4.0

v6.3.0

17 Dec 14:28

Choose a tag to compare

Major Features

  • RFC compliance for JSON Patch and JSON Merge Patch
  • Big endian architecture support
  • std::chrono JSON support
  • Enhanced BEVE format streaming capabilities

Big Endian Support

Full support for big endian architectures with compile-time detection via std::endian::native. Includes byte-swapping implementations across all components, with CI testing through GCC cross-compilation and QEMU. (Closes #1675)

JSON Patch (RFC 6902)

Complete implementation of RFC 6902 JSON Patch for computing and applying document differences:

  • glz::diff() - Generate patches between documents
  • glz::patch() - Apply operations in-place
  • glz::patched() - Non-mutating patch application
  • glz::patch_json() - Work directly with JSON strings
  • All six operations: add, remove, replace, move, copy, test
  • Atomic transactions with automatic rollback on failure
  • Option to create missing intermediate paths
  • #2131

JSON Merge Patch (RFC 7386)

Full support for RFC 7386 JSON Merge Patch:

  • merge_patch() - Apply patches in-place
  • merge_patched() - Returns new patched value
  • merge_diff() - Generate patches between documents
  • Correct handling of null-value removal, recursive merging, and array replacement
  • #2132

std::chrono Support

Zero-allocation serialization for chrono types: (Closes #1110)

  • std::chrono::duration - Serialized as numeric count
  • std::chrono::system_clock::time_point - ISO 8601 UTC format
  • std::chrono::steady_clock::time_point - Numeric format
  • Epoch wrappers: epoch_seconds, epoch_millis, epoch_micros, epoch_nanos
  • Precision-aware fractional seconds based on duration type
  • Automatic timezone offset conversion to UTC
  • #2130

BEVE Delimiter and Incremental Writing

New streaming capabilities for BEVE (Binary Efficient Value Encoding) similar to NDJSON for JSON:

  • write_beve_delimiter() - Outputs delimiter byte (0x06)
  • write_beve_append() - Adds values without clearing buffer
  • write_beve_append_with_delimiter() - Streaming-friendly writes
  • write_beve_delimited() - Container serialization with delimiters
  • read_beve_delimited() - Read delimiter-separated values
  • read_beve_at() - Offset-based reading with automatic delimiter skipping

When converting delimited BEVE to JSON via beve_to_json, delimiters become newlines for NDJSON-compatible output.

std::u8string and std::u8string_view Support

Native serialization support for UTF-8 string types.

mimic Type in glz::meta

New mimic type alias to prevent double-quoting of custom types as map keys: (Closes #1477)

template <>
struct glz::meta<my_key> {
   using mimic = std::string;
   static constexpr auto value = &my_key::value;
};

Networking Improvements

  • HTTP Server Keep Alive - Persistent connection support for HTTP servers #2128
  • WebSocket internal() Methods - Access underlying implementation via internal() and socket() methods #2140

Performance Improvements

  • Reduced template instantiations when various glz::opts are used, decreasing compile times #2138
  • Pass end iterator by value for higher performance in parsing #2133
  • Pass std::string_view by value throughout codebase #2134
  • Remove reinterpret_cast from atoi implementation #2136

Code Cleanup

  • Removed legacy hash_map implementation and cleaned up variant hashing #2135

Bug Fixes

  • Fixed glz::seek for invalid paths to maps by using find #2129

Breaking Changes

  • Error code renamed: get_nonexistent_json_ptrnonexistent_json_ptr for consistency #2131

Full Changelog: v6.2.0...v6.3.0

v6.2.0

11 Dec 14:35

Choose a tag to compare

v6.2.0

Major networking and RPC enhancements, including JSON RPC 2.0 registry support, zero-copy REPE handling, and a standardized ABI-stable plugin interface for REPE.

Breaking Changes

  • Move append_arrays and error_on_const_read options out of glz::opts by @stephenberry in #2110

  • WebSocket Client: ctx_ changed to context() method by @stephenberry in #2106

    // Before (won't compile)
    client.ctx_->stop();
    
    // After
    client.context()->stop();

Highlights

JSON RPC 2.0 Registry Support

Added support for JSON RPC 2.0 protocol to the registry, enabling standard JSON-based remote procedure calls alongside REPE.

struct my_api
{
   int counter = 0;
   std::string greet() { return "Hello, World!"; }
   int add(int value) { counter += value; return counter; }
};

// Create a JSON-RPC registry
glz::registry<glz::opts{}, glz::JSONRPC> server{};

my_api api{};
server.on(api);

// Call a function
auto response = server.call(R"({"jsonrpc":"2.0","method":"greet","id":1})");
// Returns: {"jsonrpc":"2.0","result":"Hello, World!","id":1}

// Read a variable
response = server.call(R"({"jsonrpc":"2.0","method":"counter","id":2})");
// Returns: {"jsonrpc":"2.0","result":0,"id":2}

// Call a function with parameters
response = server.call(R"({"jsonrpc":"2.0","method":"add","params":10,"id":3})");
// Returns: {"jsonrpc":"2.0","result":10,"id":3}

REPE Plugin Interface

A new standardized plugin interface for REPE enables ABI-stable dynamic plugin systems that work seamlessly with glz::registry and glz::asio_server. This includes:

  • Pure C header (plugin.h) for cross-compiler compatibility
  • C++ helper (plugin_helper.hpp) for implementing plugins using glz::registry
  • Interface versioning for safe plugin loading
extern "C" {
    uint32_t repe_plugin_interface_version() { return REPE_PLUGIN_INTERFACE_VERSION; }
    const char* repe_plugin_name() { return "calculator"; }
    repe_buffer repe_plugin_call(const char* request, uint64_t request_size) {
        return glz::repe::plugin_call(registry, request, request_size);
    }
}

Zero-Copy REPE Handling

True zero-copy implementation for the REPE RPC protocol, eliminating unnecessary memory allocations and copies in the hot path:

  • parse_request returns views into the original buffer
  • response_builder writes directly to output buffer
server.call = [](std::span<const char> request, std::string& response_buffer) {
    auto result = glz::repe::parse_request(request);
    // req.query and req.body are views into request
    registry.call(request, response_buffer);  // Zero-copy
};

Indexed rename_key API

A new indexed rename_key API allows transforming JSON keys based on member type information at compile time. This is useful for automatically using enum type names as JSON keys:

template <>
struct glz::meta<AppContext> {
    template <size_t Index>
    static constexpr auto rename_key() {
        using MemberType = glz::member_type_t<AppContext, Index>;

        if constexpr (std::is_enum_v<MemberType>) {
            return glz::name_v<MemberType>;
        } else {
            return glz::member_nameof<Index, AppContext>;
        }
    }
};

Output: {"num":42,"MyEnum":"Second","MyFlag":"Yes"}

New Compile Time Options

  • skip_null_members_on_read - Skip null values when reading, preserving existing values by @stephenberry in #2086
  • skip_self_constraint - Disable self constraint validation via a compile time option by @stephenberry in #2121

Improvements

Fixes

Testing

Documentation

Extensive documentation added:

Full Changelog: v6.1.0...v6.2.0

v6.1.0

23 Nov 01:04

Choose a tag to compare

Lots of improvements as I've been working through the active Glaze issues.

Breaking Changes

  • Remove bools_as_numbers from glz::opts by @stephenberry in #2008
    This option is still available, it is just no longer a core glz::opts option, to reduce the size of compilation errors.

Improvements

Fixes

Testing

New Contributors

Full Changelog: v6.0.3...v6.1.0

v6.0.3

10 Nov 23:38

Choose a tag to compare

Improvements

  • glz::get for glz::generic and containers by @stephenberry in #2052
    This change also adds much faster glz::generic support reading into compatible types
  • BEVE skip null members support by @stephenberry in #2054

Fixes

Full Changelog: v6.0.2...v6.0.3

v6.0.2

06 Nov 20:02

Choose a tag to compare

New Features

  • skip_if runtime value skipping in #2029

skip_if documentation

struct user_settings_t {
    std::string theme = "light";
    int volume = 50;
};

template <>
struct glz::meta<user_settings_t> {
    template <class T>
    static constexpr bool skip_if(T&& value, std::string_view key, const 
glz::meta_context&) {
        using V = std::decay_t<T>;
        if constexpr (std::same_as<V, std::string>) {
            return key == "theme" && value == "light";
        }
        else if constexpr (std::same_as<V, int>) {
            return key == "volume" && value == 50;
        }
        return false;
    }
};
  • REPE to/from JSON RPC 2.0 in #2026

Improvements

  • Support for nullable_value_t with BEVE in #2021
  • Prevent Clang missing braces warnings in #2024

Fixes

Full Changelog: v6.0.1...v6.0.2

v6.0.1

22 Oct 13:53

Choose a tag to compare

Improvements

Fixes

  • Checking for Opts.comments when skipping ws to fix JSONC parse issue by @stephenberry in #2005
  • Fixed read_constraint optional handling with missing-key option by @stephenberry in #2010

Full Changelog: v6.0.0...v6.0.1