SkillAgentSearch skills...

Glaze

Extremely fast, in memory, JSON and reflection library for modern C++. BEVE, CBOR, CSV, MessagePack, TOML, YAML, EETF

Install / Use

/learn @stephenberry/Glaze

README

Glaze

One of the fastest JSON libraries in the world. Glaze reads and writes from object memory, simplifying interfaces and offering incredible performance.

Formats Supported:

  • JSON | glaze/json.hpp
  • BEVE (Binary Efficient Versatile Encoding) | glaze/beve.hpp
  • CBOR (Concise Binary Object Representation) | glaze/cbor.hpp
  • CSV (Comma Separated Value) | glaze/csv.hpp
  • MessagePack | glaze/msgpack.hpp
  • Stencil/Mustache (string interpolation) | glaze/stencil/stencil.hpp
  • TOML 1.1 (Tom's Obvious, Minimal Language) | glaze/toml.hpp
  • YAML | glaze/yaml.hpp
  • EETF (Erlang External Term Format) | glaze/eetf.hpp
  • And Many More Features

[!NOTE]

Glaze is getting HTTP support with REST servers, clients, websockets, and more. The networking side of Glaze is under active development, and while it is usable and feedback is desired, the API is likely to be changing and improving.

With C++23 & C++26 compile time reflection for MSVC, Clang, and GCC!

C++26 P2996 Reflection Support

Glaze now supports P2996 "Reflection for C++26". When enabled, P2996 unlocks capabilities that aren't possible with traditional compile-time reflection:

  • Non-aggregate types — classes with constructors, virtual functions, and inheritance just work
  • Automatic enum serialization — no glz::meta needed, enums serialize to strings automatically
  • Unlimited struct members — no 128-member cap
  • Private member access — reflect on all members regardless of access specifiers
  • Standardized — no compiler-specific hacks, built on std::meta
// Classes with constructors — just works with P2996
class User {
public:
   std::string name;
   int age;
   User() = default;
   User(std::string n, int a) : name(std::move(n)), age(a) {}
};

User u{"Alice", 30};
auto json = glz::write_json(u).value_or("error");
// {"name":"Alice","age":30}

// Enums serialize as strings — no glz::meta required
enum class Color { Red, Green, Blue };
Color c = Color::Green;

struct reflect_enums_opts : glz::opts {
   bool reflect_enums = true;
};
auto color_json = glz::write<reflect_enums_opts{}>(c).value_or("error");
// "Green"

Supported compilers: GCC 16+ (-std=c++26 -freflection) and Bloomberg clang-p2996. See the P2996 documentation for setup and details.

📖 Documentation

See this README, the Glaze Documentation Page, or docs folder for documentation.

Highlights

  • Pure, compile time reflection for structs
    • Powerful meta specialization system for custom names and behavior
    • C++26 P2996 reflection support — non-aggregates, automatic enums, unlimited members
  • JSON RFC 8259 compliance with UTF-8 validation
  • Standard C++ library support
  • Header only
  • Direct to memory serialization/deserialization
  • Compile time maps with constant time lookups and perfect hashing
  • Powerful wrappers to modify read/write behavior (Wrappers)
  • Use your own custom read/write functions (Custom Read/Write)
  • Handle unknown keys in a fast and flexible manner
  • Direct memory access through JSON pointer syntax
  • JMESPath querying
  • No exceptions (compiles with -fno-exceptions)
  • No runtime type information necessary (compiles with -fno-rtti)
  • JSON Schema generation
  • Partial Read and Partial Write support
  • Streaming I/O for reading/writing large files with bounded memory
  • Much more!

Performance

| Library | Roundtrip Time (s) | Write (MB/s) | Read (MB/s) | | ------------------------------------------------------------ | ------------------ | ------------ | ----------- | | Glaze | 1.01 | 1396 | 1200 | | simdjson (on demand) | N/A | N/A | 1163 | | yyjson | 1.22 | 1023 | 1106 | | reflect_cpp | 3.15 | 488 | 365 | | daw_json_link | 3.29 | 334 | 479 | | RapidJSON | 3.76 | 289 | 416 | | json_struct | 5.87 | 178 | 316 | | Boost.JSON | 5.38 | 198 | 308 | | nlohmann | 15.44 | 86 | 81 |

Performance test code available here

Performance caveats: simdjson and yyjson are great, but they experience major performance losses when the data is not in the expected sequence or any keys are missing (the problem grows as the file size increases, as they must re-iterate through the document).

Also, simdjson and yyjson do not support automatic escaped string handling, so if any of the currently non-escaped strings in this benchmark were to contain an escape, the escapes would not be handled.

ABC Test shows how simdjson has poor performance when keys are not in the expected sequence:

| Library | Read (MB/s) | | ------------------------------------------------------------ | ----------- | | Glaze | 1219 | | simdjson (on demand) | 89 |

Binary Performance

Tagged binary specification: BEVE

| Metric | Roundtrip Time (s) | Write (MB/s) | Read (MB/s) | | --------------------- | ------------------ | ------------ | ----------- | | Raw performance | 0.42 | 3235 | 2468 | | Equivalent JSON data* | 0.42 | 3547 | 2706 |

JSON size: 670 bytes

BEVE size: 611 bytes

*BEVE packs more efficiently than JSON, so transporting the same data is even faster.

Examples

[!TIP]

See the example_json unit test for basic examples of how to use Glaze. See json_test for an extensive test of features.

Your struct will automatically get reflected! No metadata is required by the user.

struct my_struct
{
  int i = 287;
  double d = 3.14;
  std::string hello = "Hello World";
  std::array<uint64_t, 3> arr = { 1, 2, 3 };
  std::map<std::string, int> map{{"one", 1}, {"two", 2}};
};

JSON (prettified)

{
   "i": 287,
   "d": 3.14,
   "hello": "Hello World",
   "arr": [
      1,
      2,
      3
   ],
   "map": {
      "one": 1,
      "two": 2
   }
}

Write JSON

my_struct s{};
std::string buffer = glz::write_json(s).value_or("error");

or

my_struct s{};
std::string buffer{};
auto ec = glz::write_json(s, buffer);
if (ec) {
  // handle error
}

Read JSON

std::string buffer = R"({"i":287,"d":3.14,"hello":"Hello World","arr":[1,2,3],"map":{"one":1,"two":2}})";
auto s = glz::read_json<my_struct>(buffer);
if (s) // check std::expected
{
  s.value(); // s.value() is a my_struct populated from buffer
}

or

std::string buffer = R"({"i":287,"d":3.14,"hello":"Hello World","arr":[1,2,3],"map":{"one":1,"two":2}})";
my_struct s{};
auto ec = glz::read_json(s, buffer); // populates s from buffer
if (ec) {
  // handle error
}

Read/Write From File

auto ec = glz::read_file_json(obj, "./obj.json", std::string{});
auto ec = glz::write_file_json(obj, "./obj.json", std::string{});

[!IMPORTANT]

The file name (2nd argument), must be null terminated.

Writing to Streams

For streaming to std::ostream destinations (files, network, etc.) with bounded memory:

#include "glaze/core/ostream_buffer.hpp"

std::ofstream file("output.json");
glz::basic_ostream_buffer<std::ofstre
View on GitHub
GitHub Stars2.5k
CategoryDevelopment
Updated4h ago
Forks223

Languages

C++

Security Score

100/100

Audited on Mar 27, 2026

No findings