From c73ee6cb692dffdf9bf159a2b11e501588939be1 Mon Sep 17 00:00:00 2001 From: Ramya Eliger Date: Thu, 6 Aug 2026 16:00:21 +0530 Subject: [PATCH 1/4] fix required member check for described structs in parse_into --- include/boost/json/detail/parse_into.hpp | 11 ++++++++++- test/parse_into.cpp | 18 ++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/include/boost/json/detail/parse_into.hpp b/include/boost/json/detail/parse_into.hpp index 003c8d3d1..e8a2fa3dc 100644 --- a/include/boost/json/detail/parse_into.hpp +++ b/include/boost/json/detail/parse_into.hpp @@ -18,6 +18,7 @@ #include #include +#include #include /* @@ -1153,6 +1154,7 @@ class converting_handler handler_tuple handlers_; int inner_active_ = -1; std::size_t activated_ = 0; + std::array::value> seen_ = {}; public: converting_handler( converting_handler const& ) = delete; @@ -1183,8 +1185,11 @@ class converting_handler bool required_member = mp11::mp_with_index( inner_active_, is_required_checker{}); - if( required_member ) + if( required_member && !seen_[inner_active_] ) + { + seen_[inner_active_] = true; ++activated_; + } key_ = {}; inner_active_ = -1; @@ -1214,7 +1219,11 @@ class converting_handler bool on_object_begin( system::error_code& ec ) { if( inner_active_ < 0 ) + { + activated_ = 0; + seen_ = {}; return true; + } BOOST_JSON_INVOKE_INNER( on_object_begin(ec) ); } diff --git a/test/parse_into.cpp b/test/parse_into.cpp index 241591fea..2fa778184 100644 --- a/test/parse_into.cpp +++ b/test/parse_into.cpp @@ -426,6 +426,24 @@ class parse_into_test {"b", 3.14f}, {"c", "hello"}}}}; testParseIntoValue(unexpected_jo); + + system::error_code ec; + X x{}; + parse_into(x, R"( {"a": 1, "a": 2, "a": 3} )", ec); + BOOST_TEST( ec == error::size_mismatch ); + + std::vector v; + ec = {}; + parse_into( + v, R"( [{"a": 1, "b": 1, "c": "one"}, {"a": 2}] )", ec); + BOOST_TEST( ec == error::size_mismatch ); + + ec = {}; + parse_into( + v, + R"( [{"a": 1, "b": 1, "c": "one"}, {"a": 2, "b": 2, "c": "two"}] )", + ec); + BOOST_TEST( !ec.failed() ) && BOOST_TEST( v.size() == 2 ); #endif } From 5b64aac6814d9504d19a2ea4846ca97644da8fa9 Mon Sep 17 00:00:00 2001 From: Ramya Eliger Date: Sat, 8 Aug 2026 13:02:08 +0530 Subject: [PATCH 2/4] use std::bitset for the seen-members record --- include/boost/json/detail/parse_into.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/json/detail/parse_into.hpp b/include/boost/json/detail/parse_into.hpp index e8a2fa3dc..d9a94d26b 100644 --- a/include/boost/json/detail/parse_into.hpp +++ b/include/boost/json/detail/parse_into.hpp @@ -18,7 +18,7 @@ #include #include -#include +#include #include /* @@ -1154,7 +1154,7 @@ class converting_handler handler_tuple handlers_; int inner_active_ = -1; std::size_t activated_ = 0; - std::array::value> seen_ = {}; + std::bitset::value> seen_; public: converting_handler( converting_handler const& ) = delete; @@ -1221,7 +1221,7 @@ class converting_handler if( inner_active_ < 0 ) { activated_ = 0; - seen_ = {}; + seen_.reset(); return true; } From 6bf6d78bcfa817dfc6c548124562308c922acbfe Mon Sep 17 00:00:00 2001 From: Ramya Eliger Date: Wed, 12 Aug 2026 15:03:08 +0530 Subject: [PATCH 3/4] remove activated_, count required members via seen_ --- include/boost/json/detail/parse_into.hpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/include/boost/json/detail/parse_into.hpp b/include/boost/json/detail/parse_into.hpp index d9a94d26b..756388c93 100644 --- a/include/boost/json/detail/parse_into.hpp +++ b/include/boost/json/detail/parse_into.hpp @@ -1153,7 +1153,6 @@ class converting_handler handler_tuple handlers_; int inner_active_ = -1; - std::size_t activated_ = 0; std::bitset::value> seen_; public: @@ -1185,11 +1184,8 @@ class converting_handler bool required_member = mp11::mp_with_index( inner_active_, is_required_checker{}); - if( required_member && !seen_[inner_active_] ) - { + if( required_member ) seen_[inner_active_] = true; - ++activated_; - } key_ = {}; inner_active_ = -1; @@ -1220,7 +1216,6 @@ class converting_handler { if( inner_active_ < 0 ) { - activated_ = 0; seen_.reset(); return true; } @@ -1234,7 +1229,7 @@ class converting_handler { using C = mp11::mp_count_if; constexpr int N = mp11::mp_size
::value - C::value; - if( activated_ < N ) + if( seen_.count() < N ) { BOOST_JSON_FAIL( ec, error::size_mismatch ); return false; From 9e9458f4572dd5b43cd74a319d2b72df84ba693f Mon Sep 17 00:00:00 2001 From: Ramya Eliger Date: Thu, 13 Aug 2026 12:10:45 +0530 Subject: [PATCH 4/4] check seen_.all() instead of counting required members --- include/boost/json/detail/parse_into.hpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/include/boost/json/detail/parse_into.hpp b/include/boost/json/detail/parse_into.hpp index 756388c93..d68fce1a9 100644 --- a/include/boost/json/detail/parse_into.hpp +++ b/include/boost/json/detail/parse_into.hpp @@ -1216,7 +1216,14 @@ class converting_handler { if( inner_active_ < 0 ) { - seen_.reset(); + // optional members count as seen from the start, so that at the + // end of the object seen_.all() means no required member is + // missing + mp11::mp_for_each< mp11::mp_iota< mp11::mp_size
> >( + [&](auto I) { + using T = mp11::mp_at< Dt, decltype(I) >; + seen_[I] = is_optional_like::value; + }); return true; } @@ -1227,9 +1234,7 @@ class converting_handler { if( inner_active_ < 0 ) { - using C = mp11::mp_count_if; - constexpr int N = mp11::mp_size
::value - C::value; - if( seen_.count() < N ) + if( !seen_.all() ) { BOOST_JSON_FAIL( ec, error::size_mismatch ); return false;