-
-
Notifications
You must be signed in to change notification settings - Fork 7.1k
Templated versions of NLOHMANN_DEFINE_TYPE_INTRUSIVE and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE #2532
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Templated versions of NLOHMANN_DEFINE_TYPE_INTRUSIVE and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE #2532
Conversation
…_TYPE_NON_INTRUSIVE_2 added to make work with arbitrary basic_json overloads easier.
Tests should to to |
…define_type_macroses
Thanks for the proposal, I like it! In fact, the introduction of I'm hesitant on replacing the existing macros, because this may break existing code, wouldn't it? |
Theoretically, it shouldn't I just added template parametrisation of json type, but who knows. There are only a few tests that check this macro. But problems may occur in some real-life usage that is hard to predict. BTW, it's better to constrain template type somehow. enable_if<is_basic_json>? |
I added TODO section in PR description |
…_DEFINE_TYPE_NON_INTRUSIVE_2 updated to match NLOHMANN_JSON_SERIALIZE_ENUM
Speaking about this. Actually, it's quite easy to find all the problematic places. Just search "nlohmann::json" with full words option. /*!
@brief macro
@def NLOHMANN_DEFINE_TYPE_INTRUSIVE
@since version 3.9.0
*/
#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
/*!
@brief macro
@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
@since version 3.9.0
*/
#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } /*!
@brief SAX interface
This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
Each function is called in different situations while the input is parsed. The
boolean return value informs the parser whether to continue processing the
input.
*/
template<typename BasicJsonType>
struct json_sax
{ /// hash value for JSON objects
template<>
struct hash<nlohmann::json>
{
/*!
@brief return a hash value for a JSON object
@since version 1.0.0
*/
std::size_t operator()(const nlohmann::json& j) const
{
return nlohmann::detail::hash(j);
}
}; /*!
@brief exchanges the values of two JSON objects
@since version 1.0.0
*/
template<>
inline void swap<nlohmann::json>(nlohmann::json& j1, nlohmann::json& j2) noexcept(
is_nothrow_move_constructible<nlohmann::json>::value&&
is_nothrow_move_assignable<nlohmann::json>::value
)
{
j1.swap(j2);
} /*!
@brief user-defined string literal for JSON values
This operator implements a user-defined string literal for JSON objects. It
can be used by adding `"_json"` to a string literal and returns a JSON object
if no parse error occurred.
@param[in] s a string representation of a JSON object
@param[in] n the length of string @a s
@return a JSON object
@since version 1.0.0
*/
JSON_HEDLEY_NON_NULL(1)
inline nlohmann::json operator "" _json(const char* s, std::size_t n)
{
return nlohmann::json::parse(s, s + n);
}
/*!
@brief user-defined string literal for JSON pointer
This operator implements a user-defined string literal for JSON Pointers. It
can be used by adding `"_json_pointer"` to a string literal and returns a JSON pointer
object if no parse error occurred.
@param[in] s a string representation of a JSON Pointer
@param[in] n the length of string @a s
@return a JSON pointer object
@since version 2.0.0
*/
JSON_HEDLEY_NON_NULL(1)
inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
{
return nlohmann::json::json_pointer(std::string(s, n));
} It seems more like too strict glueing to nlohmann::json despite the fact that it's just default specialization, not only one. |
Some possible improvements for NLOHMANN_DEFINE_TYPE_INTRUSIVE and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE. I'm not sure should it be done in this PR or not. /*!
@brief macro to briefly define intrusive serialization of a given type to/from JSON
@note you can define your own specialized macroses like NLOHMANN_DEFINE_TYPE_INTRUSIVE
@def NLOHMANN_DEFINE_TYPE_INTRUSIVE_IMPL
@since version 3.9.2
*/
#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_IMPL(BasicJsonType, Type, ...) \
friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
/*!
@brief macro to briefly define non-intrusive serialization of a given type to/from JSON
@note you can define your own specialized macroses like NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_IMPL
@since version 3.9.2
*/
#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_IMPL(BasicJsonType, Type, ...) \
inline void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
inline void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
/*!
@brief macro to briefly define intrusive serialization of given type to/from nlohmann::json
@def NLOHMANN_DEFINE_TYPE_INTRUSIVE
@since version 3.9.0
@sa NLOHMANN_DEFINE_TYPE_INTRUSIVE_IMPL
*/
#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) NLOHMANN_DEFINE_TYPE_INTRUSIVE_IMPL(nlohmann::json, Type, __VA_ARGS__)
/*!
@brief macro to briefly define non-intrusive serialization of given type to/from nlohmann::json
@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
@since version 3.9.0
@sa NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_IMPL
*/
#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_IMPL(nlohmann::json, Type, __VA_ARGS__) |
…_TYPE_NON_INTRUSIVE_2 are renamed to *_T. Also doxygen docs for them are improved
Thanks for checking - the other usages of |
…ce code bloat in unit-udt_macro.cpp
…RUSIVE_T after "Template declaration of NLOHMANN_DEFINE_TYPE_INTRUSIVE_2 and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_2 updated to match NLOHMANN_JSON_SERIALIZE_ENUM"
…ON_INTRUSIVE_T are added in unit-udt_macro.cpp. Needed to patch doctest.h to workaround doctest/doctest#447
…USIVE_IMPL are added. NLOHMANN_DEFINE_TYPE_INTRUSIVE and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE are updated to work via XXX_IMPL verions. Also doxygen documentation is improved
Tests are added. PR is ready to review. |
…define_type_macroses
…define_type_macroses # Conflicts: # test/src/unit-udt_macro.cpp
Are there any possible use cases where just making the original macros templated would break backwards compat? I personally think it'd be a lot cleaner if the macros were changed rather than making new ones that do the same thing. Although, I'm sure you agree and are just erring on the side of caution 🙂 Just not sure if the caution is needed necessarily. |
There are a lot of users with different compilers. Who knows what can go wrong. A separate macro at least minimizes the chance of problems. But of course, I can just replace the content of the existing macro with my templated version, if the owner says so. Unfortunately, 3 months passed and there is still zero feedback from nlohmann about the final version. |
@YarikTH Sorry for leaving this open for so long... Can you please update to the latest develop version. I think the only remaining todos are documentation. |
I'm no longer interested in this PR. If someone wants to continue it, you are welcome. |
As I described in #2528 (comment)
Ideally, NLOHMANN_DEFINE_TYPE_INTRUSIVE and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE should work with any basic_json overload.
Like here:
https://godbolt.org/z/d16erK
In this pull request, I added my templated macroses as two new macroses with ugly names
NLOHMANN_DEFINE_TYPE_INTRUSIVE_2
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_2
I'm not sure if their content should just replace NLOHMANN_DEFINE_TYPE_INTRUSIVE and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE or they should be separated, but have a better name (suggestions are welcome!).
Also any way some tests should be written for them, but I don't know where. Maybe in unit-udt_macro.cpp? I have to include ordered_json to it in this case.
TODO:
Pull request checklist
Read the Contribution Guidelines for detailed information.
include/nlohmann
directory, runmake amalgamate
to create the single-header filesingle_include/nlohmann/json.hpp
. The whole process is described here.