From bb4c52285896874ffe676de2c27e7462d8e32b21 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Mon, 20 Jul 2026 23:33:36 +0000 Subject: [PATCH] Flush serializer buffer in dump_escaped unit test test-convenience failed (macOS finished first; the failure is platform-independent) because check_escaped() calls the internal serializer::dump_escaped() directly and then reads the output stream. Since dump_escaped() now writes into the serializer's internal write buffer, the bytes were still buffered and the stream was empty. Expose flush() under JSON_PRIVATE_UNLESS_TESTED (same visibility as dump_escaped) and flush in check_escaped() before inspecting the output. Per-string flushing inside dump_escaped() was rejected on purpose: it would defeat the buffering that makes object/array-heavy dumps faster. Library behavior is unchanged (flush()'s body is identical; only its access label moved). Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01XAYM1qhSA2FDaDcGfPW3fG Signed-off-by: Niels Lohmann --- include/nlohmann/detail/output/serializer.hpp | 6 ++++++ single_include/nlohmann/json.hpp | 6 ++++++ tests/src/unit-convenience.cpp | 1 + 3 files changed, 13 insertions(+) diff --git a/include/nlohmann/detail/output/serializer.hpp b/include/nlohmann/detail/output/serializer.hpp index 7d6b3d2ce..948ae420a 100644 --- a/include/nlohmann/detail/output/serializer.hpp +++ b/include/nlohmann/detail/output/serializer.hpp @@ -730,12 +730,17 @@ class serializer write_buffer_pos += length; } + JSON_PRIVATE_UNLESS_TESTED: /*! @brief flush the write buffer to the output adapter Writing zero characters is a well-defined no-op for every output adapter, so the buffered length is passed through unconditionally (no empty-guard branch to leave uncovered). + + @note dump_escaped() and dump_integer()/dump_float() write into the internal + write buffer; callers that invoke them directly (rather than through the + public dump()) must call flush() before inspecting the output. */ void flush() { @@ -743,6 +748,7 @@ class serializer write_buffer_pos = 0; } + private: /*! @brief count digits diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index a08320d33..ffbac824c 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -21313,12 +21313,17 @@ class serializer write_buffer_pos += length; } + JSON_PRIVATE_UNLESS_TESTED: /*! @brief flush the write buffer to the output adapter Writing zero characters is a well-defined no-op for every output adapter, so the buffered length is passed through unconditionally (no empty-guard branch to leave uncovered). + + @note dump_escaped() and dump_integer()/dump_float() write into the internal + write buffer; callers that invoke them directly (rather than through the + public dump()) must call flush() before inspecting the output. */ void flush() { @@ -21326,6 +21331,7 @@ class serializer write_buffer_pos = 0; } + private: /*! @brief count digits diff --git a/tests/src/unit-convenience.cpp b/tests/src/unit-convenience.cpp index 037a4e589..839f1c86e 100644 --- a/tests/src/unit-convenience.cpp +++ b/tests/src/unit-convenience.cpp @@ -100,6 +100,7 @@ void check_escaped(const char* original, const char* escaped, const bool ensure_ std::stringstream ss; json::serializer s(nlohmann::detail::output_adapter(ss), ' '); s.dump_escaped(original, ensure_ascii); + s.flush(); // dump_escaped writes into the serializer's internal buffer CHECK(ss.str() == escaped); } } // namespace