Releases: stephenberry/glaze
v4.2.3
Improvements
- Improved compilation performance (many thanks to @arturbac) in #1512, #1514, #1516, #1513, #1517
- Remove constexpr requirement for glz::schema fields & cleaned JSON schema code by @stephenberry in #1518
Fixes
- Fixed glz::merge with empty objects in #1519 (thanks @SenseOnline)
- Fixed enum string read for vector of pairs in concatenate mode by @sjanel in #1525
In Development
- REPE conformance for registry errors in #1526
Full Changelog: v4.2.2...v4.2.3
v4.2.2
Slice support for glz::read_jmespath
std::vector<int> data{0,1,2,3,4,5,6,7,8,9};
std::string buffer{};
expect(not glz::write_json(data, buffer));
std::vector<int> slice{};
expect(not glz::read_jmespath<"[0:5]">(slice, buffer));
expect(slice.size() == 5);
expect(slice[0] == 0);
expect(slice[1] == 1);
expect(slice[2] == 2);
expect(slice[3] == 3);
expect(slice[4] == 4);
Pre-compute JMESPath run-time expressions
The run-time version of glz::read_jmespath
also now takes in a const jmespath_expression&
. This allows a jmespath_expression
to be "compiled" once in the code and reused for much better runtime performance. This caches the tokenization.
Person child{};
// A runtime expression can be pre-computed and saved for more efficient lookups
glz::jmespath_expression expression{"family.children[0]"};
expect(not glz::read_jmespath(expression, child, buffer));
expect(child.first_name == "Lilly");
Note that this still works:
expect(not glz::read_jmespath("family.children[0]", child, buffer));
by @stephenberry in #1510
Fixes
Full Changelog: v4.2.1...v4.2.2
v4.2.1
First steps for compile-time and run-time JMESPath query support
v4.2.0 neutered the partial_read
option, due to its complexity and confusing behavior (and to make it faster). This release brings another approach to partial reading that is far more extensible, by utilizing the JMESPath query specification.
More JMESPath support will be added in the future, but this release brings both compile-time and run-time JMESPath expression handling to read a value at a target location in a buffer.
Example
struct Person
{
std::string first_name{};
std::string last_name{};
uint16_t age{};
};
struct Family
{
Person father{};
Person mother{};
std::vector<Person> children{};
};
struct Home
{
Family family{};
std::string address{};
};
suite jmespath_read_at_tests = [] {
"compile-time read_jmespath"_test = [] {
Home home{.family = {.father = {"Gilbert", "Fox", 28},
.mother = {"Anne", "Fox", 30},
.children = {{"Lilly"}, {"Vincent"}}}};
std::string buffer{};
expect(not glz::write_json(home, buffer));
std::string first_name{};
auto ec = glz::read_jmespath<"family.father.first_name">(first_name, buffer);
expect(not ec) << glz::format_error(ec, buffer);
expect(first_name == "Gilbert");
Person child{};
expect(not glz::read_jmespath<"family.children[0]">(child, buffer));
expect(child.first_name == "Lilly");
expect(not glz::read_jmespath<"family.children[1]">(child, buffer));
expect(child.first_name == "Vincent");
};
"run-time read_jmespath"_test = [] {
Home home{.family = {.father = {"Gilbert", "Fox", 28},
.mother = {"Anne", "Fox", 30},
.children = {{"Lilly"}, {"Vincent"}}}};
std::string buffer{};
expect(not glz::write_json(home, buffer));
std::string first_name{};
auto ec = glz::read_jmespath("family.father.first_name", first_name, buffer);
expect(not ec) << glz::format_error(ec, buffer);
expect(first_name == "Gilbert");
Person child{};
expect(not glz::read_jmespath("family.children[0]", child, buffer));
expect(child.first_name == "Lilly");
expect(not glz::read_jmespath("family.children[1]", child, buffer));
expect(child.first_name == "Vincent");
};
};
by @stephenberry in #1509
Other Improvements
- allow subclassing json_t by @benine203 in #1504
Full Changelog: v4.2.0...v4.2.1
v4.2.0
Breaking Partial Read Changes (Faster/Cleaner)
- The option
partial_read_nested
has been removed, to simplify partial reading and bring better performance. If the optionpartial_read
istrue
, then short circuiting will occur after the deepest value is read. This ensures that a true "partial" read occurs and post-read skipping is not necessary.- If you only want to read certain fields in a struct and perform this multiple times within a larger object, then use
glz::skip
or seterror_on_unknown_keys = false
. Either of these approaches will skip keys you don't care about.
- If you only want to read certain fields in a struct and perform this multiple times within a larger object, then use
- The local metadata for
static constexpr auto partial_read = true;
will now be ignored. You must explicitly useglz::opts{.partial_read = true}
in the Glaze options for partial reading.- The local meta parameter was a poor design choice, because we want to separate serialization logic from options, so that the same
glz::meta
information can be used with various options. It also complicated the code/API.
- The local meta parameter was a poor design choice, because we want to separate serialization logic from options, so that the same
Tip
When setting up partial reading, it is best to just include the parts of the deepest structure you care about and the parent structures to that location. This ensures the most efficient traversal to the fields of interest and the least amount of C++ struct writing.
The documentation for partial reading has been updated here: [Partial Read](https://github.com/stephenberry/glaze/blob/main/docs/partial-read.md)
by @stephenberry in #1502
Improvements
- Faster string skipping with SWAR in #1499
Full Changelog: v4.1.0...v4.2.0
v4.1.0
Improvements
- Update to fast_float v7.0.0 in #1488
- Adding example_json for newcomers to Glaze in #1490
- Document glz::convert_struct in #1491
- Faster skipping in #1495
New Reflection Feature
- glz::for_each_field in #1497
struct test_type
{
int32_t int1{};
int64_t int2{};
};
test_type var{42, 43};
glz::for_each_field(var, [](auto& field) { field += 1; });
expect(var.int1 == 43);
expect(var.int2 == 44);
In Development (Breaking Changes)
glz::mustache
has been renamed to glz::stencil
along with all other associated names. The decision was made to make a more optimal approach that does not conform strictly to the mustache specification, with the long term goal of adding compile time options that satisfy full compliance. The more generally useful string interpolation will be named stencil
and not automatically escape HTML characters.
- Sections and inverted sections in stencils
- Other stencil improvements and buffer API
by @stephenberry in #1471, #1492, #1493, #1494
Full Changelog: v4.0.3...v4.1.0
v4.0.3
Improvements
- Support for nullable value types in #1460
- This adds support for optional like types that cannot provide an operator bool() because that operator is reserved for some other action. This adds a nullable_value_t concept that only checks for value() and has_value().
- Adding
glz::convert_struct
for reflection conversion in #1472 - Faster
glz::validate_json
in #1478 - Use constructible_from rather than convertible to string_view in #1486
- Cleanup and minor optimizations by @stephenberry in #1461, #1462, #1464, #1475, #1479
Fixes
- Fix issue with variants of 1 type and tags in #1485
- validate_skipped for glz::validate_jsonc in #1476
In Development
Full Changelog: v4.0.2...v4.0.3
v4.0.2
Improvements
- Faster JSON object reading in some cases in #1442
- Simplified JSON read code in #1449
- Adding title for json schema when writing variants in #1451
Fixes
- Fixed volatile bug by @stephenberry in #1440
- Handling for escaped string reading (at least for column wise CSV) in #1446
- Avoiding _umul128, fallback to umul128_generic in MSYS2/MINGW32 by @jalius in #1453
- Eigen check for get_member to avoid invocable branch in #1458
In Development
- Asio improvementsin #1444
- Use a single vector for async_map and support atomic (non-movable) types directly in #1456
Full Changelog: v4.0.1...v4.0.2
v4.0.1
Improvements
- Integer assignment support for glz::json_t by @stephenberry in #1425
- Using a compile time linear search for partial writing index finding in #1427
Fixes
- Fix extra comma when unknown writer is empty in #1435
- Fix number parsing for glz::raw_json by @stephenberry in #1432
In Development
- Fix for asio_client call with no parameters in #1424
- Fix invalid notify check on response rather than request in #1430
- glz::async_map: using proxy rather than allocating unique_ptr in #1433
Full Changelog: v4.0.0...v4.0.1
v4.0.0
Glaze 4.0
This release brings a number of bug fixes with very few API breaking changes. The primary breaking change is a new integer parsing algorithm that is faster and rejects decimals and negative exponents to avoid implicit data loss.
New Integer Parsing Logic
When parsing integer types such as uint16_t
or int64_t
, Glaze will now reject decimal values and negative exponents, so a value such as 1.37
would produce a parse_number_failure
. This is important for avoiding implicit data loss. Developers often need to handle these conversions in various ways. Sometimes it is better to round (with various methodologies), other times truncate, and other times use the ceiling. It is recommended to use floating point types if you do not know if you will be receiving decimal values. A glz::custom
lambda in your meta can be used to invisibly convert a parsed floating point value into an integer if you do not wish to do this elsewhere.
We are open to requests for additional integer parsing options, but don't want to add complexity to Glaze unless there is a concrete need. So, please open an issue if this change causes problems.
By narrowing the definition of what it means to parse an integer in Glaze it will allow us to perform variant type deduction on integer vs floating point types. So, we will be able to parse either into an integer or a float in a variant. This has been requested a few times and would allow interfaces to avoid data loss with large integers and floating point decimal values simultaneously.
In summary, this change in integer parsing provides the benefits:
- Faster integer parsing
- No implicit data loss
- Disambiguation of integers and floats in JSON parsing to support dual integer/float types in variants and full numeric integrity
Positive exponents are still handled for integer parsing, such as 1e9
, which can save space and be easier to read than 1000000000
.
This release has no effect on integer serialization. Round-tripping in Glaze has not been affected.
Breaking Changes
-
String support for std::array<char, N> in #1247
std::array<char, N>
is now treated as a string type rather than an array of single character strings. -
Roundtrip support for
vector<pair>
, better concatenate option support, and BEVE support for these in #1418
When reading in avector<pair>
type objects are by default expected to be concatenated (as they are for output). Theconcatenate
option must be set tofalse
to read in a non-concatenated vector of pairs. Now both theconcatenate = true
andconcatenate = false
conditions properly roundtrip for both JSON and BEVE.
Improvements
- json_t assignment operators and string_view constructor in #1412
- Support for
std::atomic
in #1364 - Use clang format 18.1 in #1374
- Use jkj::dragonbox::to_decimal_ex for faster floating point serialization in #1392
- Adding roundtrip format agnostic testing in #1380
- Type "cls" or "clear" to bring the command line menu (
glz::cli_menu
) to the front in #1409
Fixes
- Removing lots of noexcept qualifiers to allow exceptions to propagate when Glaze is used with exceptions enabled in #1420
- Unknown fields fix with entirely null first object in #1367
- [Concept update] string_t with resize also needs to have .data() by @sjanel in #1372
- Support empty input NDJSON in #1381
- Fix JSON RPC documentation link to json-rpc.cpp source by @pentatonick in #1385
- Support reading into a const pointer to a member in #1387
- Fix JSON parsing from arrays to set like types with custom structs by @sjanel in #1394
- Put fast_float and dragonbox into glz namespace by @amosbird in #1398
- Naming more things beve instead of binary in #1399
- Using GLZ_ macro prefix for third party dependencies by @stephenberry in #1403
- Add missing include inside of threadpool.hpp by @X-rays5 in #1413
Active Development (use at your own risk)
- New binary REPE v1.0 spec implementation (repe::registry) in #1336
- Capture functions by reference in repe::registry by @stephenberry in #1396
- Removing repe::registry auto-locking in #1415
Full Changelog: v3.6.2...v4.0.0
v3.6.2
New AVX2 SIMD optimizations (faster string writing on some platforms)
The CMake now has the option glaze_ENABLE_AVX2. This will attempt to use AVX2 SIMD instructions in some cases to improve performance, as long as the system you are configuring on supports it. Set this option to OFF to disable the AVX2 instruction set, such as if you are cross-compiling for Arm. And, if you aren't using CMake the macro GLZ_USE_AVX2 enables the feature if defined.
- by @stephenberry in #1343
Improvements
Fixes
- Allow NDJSON in the skip_array requires statement. by @Haatschii in #1357
Full Changelog: v3.6.1...v3.6.2