Skip to content
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

Allow default values for NLOHMANN_DEFINE_TYPE_INTRUSIVE and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE #2819

Closed
wants to merge 60 commits into from
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
76f6740
Allow default values for NLOHMANN_DEFINE_TYPE_INTRUSIVE and NLOHMANN_…
harry75369 Jun 15, 2021
7aeda9d
Reverted changes for NLOHMANN_DEFINE_TYPE_INTRUSIVE and NLOHMANN_DEFI…
harry75369 Jun 22, 2021
5a5832e
Updated docs for NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT and NLOH…
harry75369 Jun 25, 2021
5664233
Rephrased docs for NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT and NL…
harry75369 Jun 25, 2021
d8ba9f4
Updated docs for NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT and NLOH…
harry75369 Jun 28, 2021
35c37c8
Renamed default_obj in to avoid name clashes
harry75369 Jun 28, 2021
f452a92
Added test for serialization of default constructed object
harry75369 Jun 28, 2021
98ac25b
Add const to getters for macro tests
harry75369 Jun 28, 2021
db0287d
trigger upstream CI
harry75369 Jul 21, 2021
a5104d1
Consistency with `using` in README.md
justanotheranonymoususer Jun 17, 2021
7ea2732
Update README.md
justanotheranonymoususer Jun 18, 2021
44201db
Update arbitrary_types.md
justanotheranonymoususer Jun 18, 2021
69de3eb
:memo: fix documentation (#2845)
nlohmann Jul 6, 2021
6c99b75
Fixes #2728
Apr 21, 2021
378fbda
fixed amalgation file for #2728
Apr 21, 2021
5a49932
include io only if JSON_NO_IO is not set for #2728
May 31, 2021
eeb48dd
fixed amalgation file for #2728
May 31, 2021
b475990
:memo: add comment for handling of negative zeros #2854
nlohmann Jul 10, 2021
1d7639a
:memo: document JSON_NO_IO macro #2842
nlohmann Jul 10, 2021
3363fc8
:rotating_light: suppress missingReturn warnings
nlohmann Jul 10, 2021
a4c9fa0
:alembic: fix coverage
nlohmann Jul 11, 2021
23803e2
Specified git branch for google benchmark fetch
grafail Jun 1, 2021
714d9f5
:bug: fix assertion failure #2838
nlohmann Jul 12, 2021
a5fd035
:bug: fix logics
nlohmann Jul 12, 2021
44a7dce
:fire: remove duplicated line
nlohmann Jul 12, 2021
45c77b1
:recycle: move capacity check to set_parent function
nlohmann Jul 13, 2021
8b643e4
:rotating_light: fix warnings
nlohmann Jul 13, 2021
97eb641
:white_check_mark: add regression test
nlohmann Jul 15, 2021
e77ae77
:recycle: simplify destroy() function for primitive types
nlohmann Jul 15, 2021
5bbbe5f
:bug: fix leak for strings
nlohmann Jul 15, 2021
16758b9
:bug: fix leak for strings
nlohmann Jul 15, 2021
88ea375
:bug: fix leak for strings
nlohmann Jul 15, 2021
3675770
:bug: fix leak for strings
nlohmann Jul 15, 2021
519dcc5
:bug: fix leak for all types
nlohmann Jul 15, 2021
94e87ff
:bulb: add comment to describe j.m_value.destroy(j.m_type) calls
nlohmann Jul 15, 2021
2d994d9
:hammer: remove noexcept annotation
nlohmann Jul 15, 2021
2668c89
:rotating_light: fix format-truncation warning #2572
nlohmann Jan 15, 2021
d65ee13
:rotating_light: suppress warning
nlohmann Jan 26, 2021
9538454
:construction_worker: fix Codacity badge
nlohmann Jul 16, 2021
8e077ae
Add a cmake option to use SYSTEM in target_include_directories
jpl-mac May 5, 2021
1f1b6a7
:white_check_mark: add test for JSON_SystemInclude flag
nlohmann Jul 16, 2021
fc0a138
:memo: update documentation
nlohmann Jul 16, 2021
3ff2517
:memo: restructure README
nlohmann Jul 16, 2021
fdb0f07
:zap: avoid string in case of empty objects
nlohmann Jul 16, 2021
740c896
:memo: add support section
nlohmann Jul 17, 2021
7e63060
:memo: fix GIF examples #2457
nlohmann Jul 17, 2021
6a81073
:art: reindent code
nlohmann Jul 19, 2021
2e82056
:arrow_up: update Doxyfile
nlohmann Jul 19, 2021
9661e66
:busts_in_silhouette: update contributors
nlohmann Jul 19, 2021
8da9e25
Refactor Unicode tests (#2889)
nlohmann Jul 21, 2021
a281280
CMake cleanup (#2885)
nlohmann Jul 22, 2021
d9562c1
Properly constrain the basic_json conversion operator
ldionne Jun 17, 2021
e9797ac
:rotating_light: fix useless-cast warnings
nlohmann Jul 30, 2021
974e386
:rotating_light: fix useless-cast warnings
nlohmann Jul 30, 2021
b83acfe
:rotating_light: fix useless-cast warnings
nlohmann Jul 30, 2021
0c4af65
:page_facing_up: add CITATION file
nlohmann Aug 1, 2021
9e7550a
:memo: add note for wstring handling
nlohmann Aug 1, 2021
8c6ea74
Supress -Wfloat-equal on intended float comparisions
Finkman Aug 3, 2021
5b6fd51
Add more suppressions on float comparisons
Finkman Aug 4, 2021
321cc51
Remove -Wfloat-equal suppressions on tests
Finkman Aug 4, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions doc/mkdocs/docs/features/arbitrary_types.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,37 +85,39 @@ Some important things:

If you just want to serialize/deserialize some structs, the `to_json`/`from_json` functions can be a lot of boilerplate.

There are two macros to make your life easier as long as you (1) want to use a JSON object as serialization and (2) want to use the member variable names as object keys in that object:
There are four macros to make your life easier as long as you (1) want to use a JSON object as serialization and (2) want to use the member variable names as object keys in that object:

- `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(name, member1, member2, ...)` is to be defined inside of the namespace of the class/struct to create code for.
- `NLOHMANN_DEFINE_TYPE_INTRUSIVE(name, member1, member2, ...)` is to be defined inside of the class/struct to create code for. This macro can also access private members.
- `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(name, member1, member2, ...)` is to be defined inside of the namespace of the class/struct to create code for.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to add a comment about the difference to the previous macros.

Furthermore, the order should be.

  • NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
  • NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT
  • NLOHMANN_DEFINE_TYPE_INTRUSIVE
  • NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT

- `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(name, member1, member2, ...)` is to be defined inside of the class/struct to create code for. This macro can also access private members.

In both macros, the first parameter is the name of the class/struct, and all remaining parameters name the members.
In all macros, the first parameter is the name of the class/struct, and all remaining parameters name the members. You can read more docs about them starting from [here](https://github.com/nlohmann/json/blob/develop/doc/mkdocs/docs/features/macros.md#nlohmann_define_type_intrusivetype-member).
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
In all macros, the first parameter is the name of the class/struct, and all remaining parameters name the members. You can read more docs about them starting from [here](https://github.com/nlohmann/json/blob/develop/doc/mkdocs/docs/features/macros.md#nlohmann_define_type_intrusivetype-member).
In all macros, the first parameter is the name of the class/struct, and all remaining parameters name the members. You can read more docs about them starting from [here](macros.md#nlohmann_define_type_intrusivetype-member).


!!! note

At most 64 member variables can be passed to `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE` or `NLOHMANN_DEFINE_TYPE_INTRUSIVE`.
At most 64 member variables can be passed to these macros.

??? example

The `to_json`/`from_json` functions for the `person` struct above can be created with:

```cpp
namespace ns {
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(person, name, address, age)
}
```

Here is an example with private members, where `NLOHMANN_DEFINE_TYPE_INTRUSIVE` is needed:

```cpp
namespace ns {
class address {
private:
std::string street;
int housenumber;
int postcode;

public:
NLOHMANN_DEFINE_TYPE_INTRUSIVE(address, street, housenumber, postcode)
};
Expand Down
14 changes: 11 additions & 3 deletions doc/mkdocs/docs/features/macros.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ The library targets C++11, but also supports some features introduced in later C
## `JSON_NOEXCEPTION`

Exceptions can be switched off by defining the symbol `JSON_NOEXCEPTION`.
When defining `JSON_NOEXCEPTION`, `#!cpp try` is replaced by `#!cpp if (true)`,
When defining `JSON_NOEXCEPTION`, `#!cpp try` is replaced by `#!cpp if (true)`,
`#!cpp catch` is replaced by `#!cpp if (false)`, and `#!cpp throw` is replaced by `#!cpp std::abort()`.

The same effect is achieved by setting the compiler flag `-fno-exceptions`.
Expand Down Expand Up @@ -55,12 +55,12 @@ When defined to `0`, implicit conversions are switched off. By default, implicit
??? example

This is an example for an implicit conversion:

```cpp
json j = "Hello, world!";
std::string s = j;
```

When `JSON_USE_IMPLICIT_CONVERSIONS` is defined to `0`, the code above does no longer compile. Instead, it must be written like this:

```cpp
Expand All @@ -79,6 +79,10 @@ The first parameter is the name of the class/struct, and all remaining parameter

See [Simplify your life with macros](arbitrary_types.md#simplify-your-life-with-macros) for an example.

## `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(type, member...)`

This macro is similar to `NLOHMANN_DEFINE_TYPE_INTRUSIVE`. It will not throw an exception in `from_json()` due to a missing value in the JSON, but can throw due to a mismatched type. In order to support that it requires that the type be default constructible. The `from_json()` function default constructs an object and uses its values as the defaults when calling the `value()` function.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
This macro is similar to `NLOHMANN_DEFINE_TYPE_INTRUSIVE`. It will not throw an exception in `from_json()` due to a missing value in the JSON, but can throw due to a mismatched type. In order to support that it requires that the type be default constructible. The `from_json()` function default constructs an object and uses its values as the defaults when calling the `value()` function.
This macro is similar to `NLOHMANN_DEFINE_TYPE_INTRUSIVE`. It will not throw an exception in `from_json()` due to a missing value in the JSON object, but can throw due to a mismatched type. In order to support that it requires that the type be default constructible. The `from_json()` function default constructs an object and uses its values as the defaults when calling the `value()` function.


## `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(type, member...)`

This macro can be used to simplify the serialization/deserialization of types if (1) want to use a JSON object as serialization and (2) want to use the member variable names as object keys in that object.
Expand All @@ -88,6 +92,10 @@ The first parameter is the name of the class/struct, and all remaining parameter

See [Simplify your life with macros](arbitrary_types.md#simplify-your-life-with-macros) for an example.

## `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(type, member...)`

This macro is similar to `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`. It will not throw an exception in `from_json()` due to a missing value in the JSON, but can throw due to a mismatched type. In order to support that it requires that the type be default constructible. The `from_json()` function default constructs an object and uses its values as the defaults when calling the `value()` function.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
This macro is similar to `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`. It will not throw an exception in `from_json()` due to a missing value in the JSON, but can throw due to a mismatched type. In order to support that it requires that the type be default constructible. The `from_json()` function default constructs an object and uses its values as the defaults when calling the `value()` function.
This macro is similar to `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`. It will not throw an exception in `from_json()` due to a missing value in the JSON object, but can throw due to a mismatched type. In order to support that it requires that the type be default constructible. The `from_json()` function default constructs an object and uses its values as the defaults when calling the `value()` function.


## `NLOHMANN_JSON_SERIALIZE_ENUM(type, ...)`

This macro simplifies the serialization/deserialization of enum types. See [Specializing enum conversion](enum_conversion.md) for more information.
9 changes: 9 additions & 0 deletions include/nlohmann/detail/macro_scope.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@

#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, default_obj.v1);

/*!
@brief macro
Expand All @@ -282,6 +283,10 @@
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__)) }

#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(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) { Type default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }

/*!
@brief macro
@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
Expand All @@ -291,6 +296,10 @@
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__)) }

#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(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) { Type default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking that having default_obj be const static would save constructing and destructing this object on every pass through the function, but there could be reasons that users wouldn't want that. I suppose that this is just something that users will need to be aware of.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Making it const static sounds a good idea. Any specific reason for not wanting that?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing in general, just could be specific use cases where having a long-lived one of these would be a problem for people.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about this, I also think having a long-lived object to be surprising.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nlohmann_json_t is already default constructed. The WITH_DEFAULT macros can just not set it if the key is missing, and then no Type default_obj; is needed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's not necessarily true. We ran into situations recently where to_json was called on a json object that already had a value, and the functions didn't clear it properly, resulting in a memory leak.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be safer to add nlohmann_json_ as prefix to default_obj to avoid name clashes.


#ifndef JSON_USE_IMPLICIT_CONVERSIONS
#define JSON_USE_IMPLICIT_CONVERSIONS 1
#endif
Expand Down
9 changes: 9 additions & 0 deletions single_include/nlohmann/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2482,6 +2482,7 @@ JSON_HEDLEY_DIAGNOSTIC_POP

#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, default_obj.v1);

/*!
@brief macro
Expand All @@ -2492,6 +2493,10 @@ JSON_HEDLEY_DIAGNOSTIC_POP
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__)) }

#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(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) { Type default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }

/*!
@brief macro
@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
Expand All @@ -2501,6 +2506,10 @@ JSON_HEDLEY_DIAGNOSTIC_POP
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__)) }

#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(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) { Type default_obj; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }

#ifndef JSON_USE_IMPLICIT_CONVERSIONS
#define JSON_USE_IMPLICIT_CONVERSIONS 1
#endif
Expand Down
103 changes: 102 additions & 1 deletion test/src/unit-udt_macro.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,42 @@ class person_with_private_data
NLOHMANN_DEFINE_TYPE_INTRUSIVE(person_with_private_data, age, name, metadata)
};

class person_with_private_data_2
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you actually test how JSON objects with missing values are serialized?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test added.

{
private:
std::string name{};
int age = 0;
json metadata = nullptr;

public:
bool operator==(const person_with_private_data_2& rhs) const
{
return name == rhs.name && age == rhs.age && metadata == rhs.metadata;
}

person_with_private_data_2() = default;
person_with_private_data_2(std::string name_, int age_, json metadata_)
: name(std::move(name_))
, age(age_)
, metadata(std::move(metadata_))
{}

std::string getName()
{
return name;
}
int getAge()
{
return age;
}
json getMetadata()
{
return metadata;
}

NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(person_with_private_data_2, age, name, metadata)
};

class person_without_private_data_1
{
public:
Expand Down Expand Up @@ -103,6 +139,41 @@ class person_without_private_data_2

NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(person_without_private_data_2, age, name, metadata)

class person_without_private_data_3
{
public:
std::string name{};
int age = 0;
json metadata = nullptr;

bool operator==(const person_without_private_data_3& rhs) const
{
return name == rhs.name && age == rhs.age && metadata == rhs.metadata;
}

person_without_private_data_3() = default;
person_without_private_data_3(std::string name_, int age_, json metadata_)
: name(std::move(name_))
, age(age_)
, metadata(std::move(metadata_))
{}

std::string getName()
{
return name;
}
int getAge()
{
return age;
}
json getMetadata()
{
return metadata;
}
};

NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(person_without_private_data_3, age, name, metadata)

class person_with_private_alphabet
{
public:
Expand Down Expand Up @@ -231,7 +302,7 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(person_with_public_alphabet, a, b, c, d, e, f

} // namespace persons

TEST_CASE_TEMPLATE("Serialization/deserialization via NLOHMANN_DEFINE_TYPE_INTRUSIVE", T,
TEST_CASE_TEMPLATE("Serialization/deserialization via NLOHMANN_DEFINE_TYPE_INTRUSIVE and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE", T,
persons::person_with_private_data,
persons::person_without_private_data_1,
persons::person_without_private_data_2)
Expand All @@ -257,6 +328,36 @@ TEST_CASE_TEMPLATE("Serialization/deserialization via NLOHMANN_DEFINE_TYPE_INTRU
}
}

TEST_CASE_TEMPLATE("Serialization/deserialization via NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT", T,
persons::person_with_private_data_2,
persons::person_without_private_data_3)
{
SECTION("person with default values")
{
// serialization
T p1("Erik", 1, {{"haircuts", 2}});
CHECK(json(p1).dump() == "{\"age\":1,\"metadata\":{\"haircuts\":2},\"name\":\"Erik\"}");

// deserialization
auto p2 = json(p1).get<T>();
CHECK(p2 == p1);

// roundtrip
CHECK(T(json(p1)) == p1);
CHECK(json(T(json(p1))) == json(p1));

// check default value in case of missing field
json j = json(p1);
j.erase("name");
j.erase("age");
j.erase("metadata");
T p3 = j.get<T>();
CHECK(p3.getName() == "");
CHECK(p3.getAge() == 0);
CHECK(p3.getMetadata() == nullptr);
}
}

TEST_CASE_TEMPLATE("Serialization/deserialization of classes with 26 public/private member variables via NLOHMANN_DEFINE_TYPE_INTRUSIVE and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE", T,
persons::person_with_private_alphabet,
persons::person_with_public_alphabet)
Expand Down