Compilation-time improvements
This release prioritizes compile time costs. Three subsystems that were previously pulled in transitively by glaze.hpp are now opt-in. If your code uses jmespath, msgpack, or recorder, you must add an explicit include.
Breaking: required includes
jmespath is now opt-in
include/glaze/json/jmespath.hpp is no longer bundled by glaze.hpp or glaze/json.hpp.
#include <glaze/json/jmespath.hpp>- Make jmespath opt in for faster compilation by @stephenberry in #2574
msgpack is now opt-in
glaze/msgpack.hpp is no longer included by the glaze.hpp aggregate header, matching the existing CBOR convention.
#include <glaze/msgpack.hpp>- Part of: Compilation time optimization and cleanup by @stephenberry in #2527
recorder is now opt-in
glaze/record/recorder.hpp is no longer included by the glaze.hpp aggregate header. This also severs the transitive glaze/csv.hpp chain that recorder pulled into every TU.
#include <glaze/record/recorder.hpp>- Part of: Compilation time optimization and cleanup by @stephenberry in #2527
glaze/json/generic.hpp split with generic_fwd.hpp
Following the same convention as glaze/forward.hpp: widely-included user headers can now reference glz::generic via the lightweight forward-only glaze/json/generic_fwd.hpp, deferring the full read/write machinery to the TUs that serialize.
Other compilation-time cleanup
A broader pass on header weight and instantiation cost:
-
New
glaze/forward.hppwith no Glaze dependencies (just<cstdint>). Users who want to specializeglz::meta,glz::to<Format, T>,glz::from<Format, T>, or constructglz::custom_tin widely-included user headers can now include only this and defer the full<glaze/glaze.hpp>include to the TUs that call read/write. -
<atomic>/<bitset>/<complex>includes incore/common.hppare now gated onGLZ_REFLECTION26(the only code that needed them). -
unique_per_length_infono longer instantiatesstd::ranges::sortperN. Measured:glz::make_keys_info<20>instantiation drops from 45.1 ms to 26.0 ms with-ftime-trace. -
boxed<T>insideglz::schemano longer dragsstd::unique_ptr<T>andstd::default_delete<T>instantiations into every TU that includesschema.hpp. -
Compilation time optimization and cleanup by @stephenberry in #2527
-
Reduce always inline usage for jsonb and bson by @stephenberry in #2572
-
perf(progress_bar): build status string withglz::to_chars+memcpyby @stephenberry in #2573
TOML: nullables, nested tables, and inline-mode cascading
This release lands four independent TOML fixes that together close most of the long-standing round-trip gaps in the parser and writer.
Inline tables and nullables (read)
The struct reader's inline-table branch now returns after parse_toml_object_members consumes the closing }. Without this, the surrounding , or } of the enclosing inline table was misparsed as the start of a new key, producing unknown_key errors on perfectly valid documents:
a = 1
inline_data = { key1 = "value1", key2 = 100 }
b = 2Nullable support is now broadly available for both TOML and YAML, including nested nullable tables and nullable arrays. nullable_emplace is consolidated as the single emplacement point.
- toml: fix inline tables parsing, support for nullables by @makekryl in #2561
- toml: fix reading nested nullable tables and nullable arrays by @makekryl in #2576
Arrays with newlines (read)
Multi-line arrays were rejected when the parser hit a newline mid-array. They are now accepted, matching the TOML spec.
Map fields and cascade inline mode through nested writers (write)
Struct fields of std::map type now emit as inline tables (items = { key = value, ... }) so the output is well-formed TOML in any nesting position. Previously they flowed through the scalar writer and produced output that could not be read back.
Inline mode now cascades through every nested writer: write_inline_value is the single dispatch point for any value written inside an inline context, and write_inline_object, write_inline_map, the array writer's write_element, the tuple/glaze_array writer, and the struct writer's PASS 1 scalar path all route through it. As a result, struct fields of vector<struct>, vector<map<...>>, optional<map>, optional<struct>, variant<...struct...>, or tuple<struct, ...> can no longer leak multi-line struct dumps or [[...]] headers inside [ ... ] or { ... }.
- Fix TOML serialization of map fields and cascade inline mode through nested writers by @stephenberry in #2544
Native JSON support for sys_days and year_month_day
std::chrono::year_month_day had no JSON specialization at all, and std::chrono::sys_days round-tripped as a full datetime. Users had to write a glz::custom lambda with std::chrono::parse to handle simple date fields, which trips compiler bugs on GCC/MSVC. Both now work directly:
struct Holiday {
std::chrono::year_month_day date;
std::string name;
};
Holiday h{2024y/6/15, "midsummer"};
glz::write_json(h); // {"date":"2024-06-15","name":"midsummer"}sys_days writes the same "YYYY-MM-DD" shape and accepts either form on read (a full datetime is floored to its UTC date).
Breaking change: write_json(sys_days{...}) used to produce "2024-06-15T00:00:00Z". It now produces "2024-06-15". Readers accept both, so upgrading on the read side is safe; producers that emit the new shape break older readers that strictly require a time component.
Safety: years outside [0000, 9999] now fail to serialize with error_code::constraint_violated instead of silently emitting wrap-around digits. This guard also covers the pre-existing system_time_point writer.
- Add native JSON support for
sys_daysandyear_month_dayby @stephenberry in #2568
HTTP: structured glz_write_error from response::body<Opts>
When glz::write failed inside response::body<Opts>(value), the response body was reset to a hardcoded literal {"error":"glz::write_json error"}. Two issues: the underlying error_ctx (code + custom message) was discarded, and the literal was appended to any partial payload the failed write had already pushed, producing malformed JSON like {"name":"abc{"error":"glz::write_json error"}.
Now the body is cleared before writing the error and a small structured value is serialized:
{"error":"glaze write failure","code":42,"message":"<custom_error_message from error_ctx>"}fix(http): emit structuredglz_write_errorfromresponse::body<Opts>on serialization failure by @genisis0x in #2565
CMake: glaze_INSTALL option
When consumed as a subproject (e.g. via FetchContent), glaze was unconditionally registering its install() and CPack rules into the parent project, causing glaze artifacts to appear in downstream installers without the consumer opting in.
A new glaze_INSTALL option defaults to ${PROJECT_IS_TOP_LEVEL}. Top-level builds keep the install rules; subproject builds skip them by default. Consumers who want the cascade can set glaze_INSTALL=ON. CMAKE_SKIP_INSTALL_RULES is still honored.
- cmake: add
glaze_INSTALLoption, default toPROJECT_IS_TOP_LEVELby @stephenberry in #2578
Cleanup
chore: fix comment typos acrossinclude/andexamples/by @genisis0x in #2567chore: remove unusedis_schema_classconcept by @genisis0x in #2569
Full Changelog: v7.6.0...v7.7.0