From ca10ccfbc968e9ab0b1c853a469b9f84a7caca5f Mon Sep 17 00:00:00 2001 From: wuyangfan <1102042793@qq.com> Date: Sun, 17 May 2026 22:33:42 +0800 Subject: [PATCH] fix: support zero-member types in NLOHMANN_DEFINE_TYPE_* macros Add NLOHMANN_JSON_PASTE0 and NLOHMANN_JSON_DOUBLE_PASTE0 so empty member lists expand to no-op serialization code. Fixes #4041. --- include/nlohmann/detail/macro_scope.hpp | 8 ++++-- tests/src/unit-udt_macro.cpp | 33 +++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index 8a7608ec36..7e5178bc7d 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -339,7 +339,9 @@ NLOHMANN_JSON_PASTE4, \ NLOHMANN_JSON_PASTE3, \ NLOHMANN_JSON_PASTE2, \ - NLOHMANN_JSON_PASTE1)(__VA_ARGS__)) + NLOHMANN_JSON_PASTE1, \ + NLOHMANN_JSON_PASTE0)(__VA_ARGS__)) +#define NLOHMANN_JSON_PASTE0(func) #define NLOHMANN_JSON_PASTE2(func, v1) func(v1) #define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2) #define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3) @@ -467,7 +469,9 @@ NLOHMANN_JSON_DOUBLE_PASTE3, \ NLOHMANN_JSON_DOUBLE_PASTE3, \ NLOHMANN_JSON_DOUBLE_PASTE1, \ - NLOHMANN_JSON_DOUBLE_PASTE1)(__VA_ARGS__)) + NLOHMANN_JSON_DOUBLE_PASTE1, \ + NLOHMANN_JSON_DOUBLE_PASTE0)(__VA_ARGS__)) +#define NLOHMANN_JSON_DOUBLE_PASTE0(func) #define NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) func(v1, v2) #define NLOHMANN_JSON_DOUBLE_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE3(func, v3, v4) #define NLOHMANN_JSON_DOUBLE_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_DOUBLE_PASTE3(func, v1, v2) NLOHMANN_JSON_DOUBLE_PASTE5(func, v3, v4, v5, v6) diff --git a/tests/src/unit-udt_macro.cpp b/tests/src/unit-udt_macro.cpp index 7fab809212..14dab29221 100644 --- a/tests/src/unit-udt_macro.cpp +++ b/tests/src/unit-udt_macro.cpp @@ -778,8 +778,41 @@ class derived_person_only_serialize_private_3 : person_without_default_construct NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE_WITH_NAMES(derived_person_only_serialize_private_3, person_without_default_constructor_3, "json_hair_color", hair_color) }; +class empty_type +{ + public: + NLOHMANN_DEFINE_TYPE_INTRUSIVE(empty_type) + + bool operator==(const empty_type& /*unused*/) const + { + return true; + } +}; + +class empty_type_non_intrusive +{}; + +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(empty_type_non_intrusive) + } // namespace persons +TEST_CASE("NLOHMANN_DEFINE_TYPE_* with zero members") +{ + SECTION("intrusive") + { + persons::empty_type v; + CHECK(json(v).dump() == "{}"); + CHECK(json::parse("{}").get() == v); + } + + SECTION("non-intrusive") + { + persons::empty_type_non_intrusive v; + CHECK(json(v).dump() == "{}"); + CHECK(json::parse("{}").get() == v); + } +} + TEST_CASE_TEMPLATE("Serialization/deserialization via NLOHMANN_DEFINE_TYPE_INTRUSIVE and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE", Pair, // NOLINT(readability-math-missing-parentheses, bugprone-throwing-static-initialization) std::pair, std::pair,