Repository navigation
Conversation
nlohmann
added this pull request to stack #5636
September 29, 2026 14:20
Owner
Author
|
Besides merging the lower CI fixes (see #5617 to #5623), commit 5484f2e reformats — posted by Claude Code on behalf of @nlohmann |
nlohmann
removed this pull request from stack #5636
September 30, 2026 13:19
nlohmann
force-pushed
the
json-view/13-view-dump
branch
from
September 30, 2026 13:20
3e2b810 to
7c179b3
Compare
nlohmann
added this pull request to stack #5739
September 30, 2026 13:21
nlohmann
force-pushed
the
json-view/13-view-dump
branch
from
September 30, 2026 15:34
7c179b3 to
bd22b6e
Compare
nlohmann
force-pushed
the
json-view/13-view-dump
branch
2 times, most recently
from
September 30, 2026 18:06
d1e2563 to
48307dc
Compare
nlohmann
marked this pull request as ready for review
September 30, 2026 18:17
nlohmann
force-pushed
the
json-view/13-view-dump
branch
from
September 30, 2026 19:15
48307dc to
bc56ac6
Compare
nlohmann
removed this pull request from stack #5739
October 6, 2026 09:26
nlohmann
changed the base branch from
json-view/12-view-values
to
json-view/11-view-access
October 6, 2026 09:26
This was referenced Oct 6, 2026
nlohmann
force-pushed
the
json-view/13-view-dump
branch
from
October 6, 2026 09:28
dfa17bd to
d26cbef
Compare
nlohmann
added this pull request to stack #5768
October 6, 2026 09:29
Add basic_json_view::dump() and the comparison operators, and read floats from the parser's digit layout instead of rescanning the token. dump(indent, indent_char, ensure_ascii, number_format) writes a value the way ordered_json::parse(text).dump() writes it for the same arguments: members in document order, all of them should a key occur more than once; strings escaped by the same rules, using the library's scanning kernels; floats written with the library's to_chars conversion, so the output equals basic_json's byte for byte; integers copied from the source, where they are already canonical, except -0, which parse() reads as 0. There is no error_handler argument, because the view only holds valid UTF-8. number_format::source copies numbers exactly as they appear in the source (e.g. "1.50", "1E2", "-0"), which basic_json cannot provide. operator<< takes the indentation from the stream width, as for basic_json. The writer walks iteratively, so nesting depth is limited by memory only. operator== and operator!= compare two views, or a view and a basic_json value in either order, by the rules basic_json's operator== uses: numbers compare by value across their types, objects compare by their members with duplicate keys resolved as parse() resolves them, member order matters only where the object type keeps one, and discarded views compare as discarded basic_json values do, including under JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON. Nothing is materialized except single scalars. While parsing, the view now records where the integer digits, the fraction digits, and the exponent of a float token are, so floats and doubles with at most 19 digits are read from that layout with the library's decimal_to_float() instead of rescanning the token. Both round correctly, so the values are those of parse(). get<double>(), materialize(), dump(), and the comparisons all use it. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
nlohmann
force-pushed
the
json-view/13-view-dump
branch
from
October 7, 2026 14:44
d26cbef to
da1ca7f
Compare
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
🔴 Amalgamation check failed! 🔴The source code has not been amalgamated and/or formatted correctly, or 📎 A ready-to-apply patch is attached to the failed workflow run as the git apply amalgamation.patchThis does not require installing astyle yourself. |
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
The source extent of a value was read from the next node, falling back to the rest of the document when that node held a decoded string. dump() of a small value could thus allocate a buffer as large as the document. Skip a few such nodes, cap the fallback estimate, and shrink a buffer that is much larger than its output. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
root() of a temporary document is deleted: its views would dangle. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
finish() copied the whole output when the buffer was more than twice as large as the result (citm dump +11%). The tighter source_extent() estimate already keeps the buffer of a small value small. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
dump() writes every member and == resolves duplicate keys as parse() does, whereas lookups find the first member of a duplicate key. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
| { | ||
| case 0: | ||
| std::snprintf(buf.data(), buf.size(), "%.17g", d); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) | ||
| static_cast<void>(std::snprintf(buf.data(), buf.size(), "%.17g", d)); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) |
| break; | ||
| case 1: | ||
| std::snprintf(buf.data(), buf.size(), "%.15g", d); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) | ||
| static_cast<void>(std::snprintf(buf.data(), buf.size(), "%.15g", d)); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) |
| break; | ||
| case 2: | ||
| std::snprintf(buf.data(), buf.size(), "%.3e", d); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) | ||
| static_cast<void>(std::snprintf(buf.data(), buf.size(), "%.3e", d)); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) |
| break; | ||
| case 3: | ||
| std::snprintf(buf.data(), buf.size(), "%.25g", d); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) | ||
| static_cast<void>(std::snprintf(buf.data(), buf.size(), "%.25g", d)); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) |
| break; | ||
| default: | ||
| std::snprintf(buf.data(), buf.size(), "%.0f", d); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) | ||
| static_cast<void>(std::snprintf(buf.data(), buf.size(), "%.0f", d)); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) |
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
The MinGW linker of the Windows clang jobs cannot link object files with more
than 32767 sections ("relocation truncated to fit: IMAGE_REL_AMD64_REL32
against `.rdata'"). unit-json_view.cpp reaches that limit as the stack
grows, so its "json_view dump" and "json_view comparison" test cases move
into unit-json_view_dump.cpp. The test generator and has_duplicate_keys()
that both files use move into json_view_test_helpers.hpp.
The new file mentions JSON_HAS_CPP_17, so it is built for C++17 like the file
it was split from.
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds
dump(),operator<<,operator==andoperator!=tobasic_json_view, and reads floats from the parser's digit layout; part of the zero-copy view stack for #5295, on top of #5622.Summary
basic_json_view::dump(indent, indent_char, ensure_ascii, number_format)writes a value the wayordered_json::parse(text).dump()writes it, for the same arguments:detail::to_chars), so the output equalsbasic_json's byte for byte;-0, whichparse()reads as 0.error_handlerargument: the view only holds valid UTF-8.number_format::source, numbers are copied exactly as they appear in the source, e.g.1.50,1E2,-0, or all digits of a long integer.basic_jsoncannot provide this.operator<<takes the indentation from the stream width, as forbasic_json.detail/view/serializer.hpp) writes through a raw pointer into a string. The walk is iterative, so the nesting depth is limited by memory only.operator==andoperator!=compare two views, or a view and abasic_jsonvalue in either order. They answer whether the valuesparse()would produce are equal bybasic_json'soperator==:1 == 1.0);parse()resolves them: the last value, at the position of the first key. (Lookups such asoperator[]still return the first member; this is documented in both places.)ordered_json) and not otherwise, exactly asbasic_jsoncompares;basic_jsonvalues do, followingJSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON.operator<.floatanddoubletokens with at most 19 digits, the value is now read from that layout instead of rescanning the token:decimal_to_float()from Speed up the lexer: own float parser, string scan, and \u table #5738: Clinger's fast path where both operands are exact, and Eisel-Lemire otherwise, which needs no fallback for up to 19 digits.parse(). Longer tokens, and other float types, keep the library's conversion of the whole token.get<double>(),materialize(),dump()and the comparisons all use it.dump,number_format,operator==,operator!=andoperator<<; the view article has a "Writing a view back" section; the pages ofbasic_json::dumpandbasic_json::operator==link to the view's counterparts. TheViewDumpbenchmark joinstests/benchmarks.Performance
Measured on Apple M1 Max (Apple clang -O2) and an x86-64 KVM VPS (GCC 13 / Clang 18 -O2, pinned to one core, about ±5-10% noise), µs, best of 3 interleaved rounds of 15 runs; files from nativejson-benchmark.
Traversing canada (every number converted), previous PR → this PR: Apple M1 2074 → 1501 (-28%), x86-64 GCC 4296 → 3505 (-18%), Clang 4331 → 3348 (-23%).
dump()at this PR (a faster writer comes later in the stack):The core library (
json::parse/dump) is unaffected: the code is view-internal (detail/view/serializer.hpp,detail/view/compare.hpp, additions todetail/view/number.hpp, small changes tomaterialize.hpp,value.hppandlookup.hpp, and new members ofbasic_json_view).Tests
The tests of
dump()and the comparisons are in a new file,tests/src/unit-json_view_dump.cpp(with helpers shared throughtests/src/json_view_test_helpers.hpp), so that no test object exceeds the 32,767 sections that the MinGW linker of the Windows clang job accepts.dump(): 2,000 generated documents compared withordered_json::dump()for indentations -1/0/2, space and tab, andensure_ascii; strings with every kind of escape; numbers (5,000 random doubles, andfloatasnumber_float_t); duplicate keys, 100,000 levels of nesting, streams and discarded views; the buffer of a small value stays small, and output that outgrows the estimate is handled.basic_json, forjsonand forordered_json; numbers, duplicate keys, member order, discarded values and 100,000 levels of nesting.float) join the bit-for-bit comparison withparse().Public API
No breaking changes. The view API is new in this stack, so nothing here changes a released interface. New members of
basic_json_view:dump,operator<<,operator==,operator!=andnumber_format. Reading floats from the digit layout changes no observable behavior, only how the value is computed.User-visible decisions in this PR:
dump()writes members in document order and writes every occurrence of a repeated key, so for ajson_viewit can differ frommaterialize().dump().operator==resolves duplicate keys asparse()does (last value), while lookups find the first member.operator<and noerror_handlerargument fordump().Written by Claude Code.
🤖 Generated with Claude Code