Skip to content

Commit 360ce45

Browse files
authored
Add serialization-only user defined type macros (nlohmann#3816)
1 parent 5d931c5 commit 360ce45

15 files changed

+293
-13
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#include <iostream>
2+
#include <nlohmann/json.hpp>
3+
4+
using json = nlohmann::json;
5+
using namespace nlohmann::literals;
6+
7+
namespace ns
8+
{
9+
class person
10+
{
11+
private:
12+
std::string name = "John Doe";
13+
std::string address = "123 Fake St";
14+
int age = -1;
15+
16+
public:
17+
// No default constructor
18+
person(std::string name_, std::string address_, int age_)
19+
: name(std::move(name_)), address(std::move(address_)), age(age_)
20+
{}
21+
22+
friend void to_json(nlohmann::json& nlohmann_json_j, const person& nlohmann_json_t)
23+
{
24+
nlohmann_json_j["name"] = nlohmann_json_t.name;
25+
nlohmann_json_j["address"] = nlohmann_json_t.address;
26+
nlohmann_json_j["age"] = nlohmann_json_t.age;
27+
}
28+
};
29+
} // namespace ns
30+
31+
int main()
32+
{
33+
ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60};
34+
35+
// serialization: person -> json
36+
json j = p;
37+
std::cout << "serialization: " << j << std::endl;
38+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#include <iostream>
2+
#include <nlohmann/json.hpp>
3+
4+
using json = nlohmann::json;
5+
using namespace nlohmann::literals;
6+
7+
namespace ns
8+
{
9+
class person
10+
{
11+
private:
12+
std::string name = "John Doe";
13+
std::string address = "123 Fake St";
14+
int age = -1;
15+
16+
public:
17+
// No default constructor
18+
person(std::string name_, std::string address_, int age_)
19+
: name(std::move(name_)), address(std::move(address_)), age(age_)
20+
{}
21+
22+
NLOHMANN_DEFINE_TYPE_INTRUSIVE(person, name, address, age)
23+
};
24+
} // namespace ns
25+
26+
int main()
27+
{
28+
ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60};
29+
30+
// serialization: person -> json
31+
json j = p;
32+
std::cout << "serialization: " << j << std::endl;
33+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#include <iostream>
2+
#include <nlohmann/json.hpp>
3+
4+
using json = nlohmann::json;
5+
using namespace nlohmann::literals;
6+
7+
namespace ns
8+
{
9+
struct person
10+
{
11+
std::string name;
12+
std::string address;
13+
int age;
14+
};
15+
16+
void to_json(nlohmann::json& nlohmann_json_j, const person& nlohmann_json_t)
17+
{
18+
nlohmann_json_j["name"] = nlohmann_json_t.name;
19+
nlohmann_json_j["address"] = nlohmann_json_t.address;
20+
nlohmann_json_j["age"] = nlohmann_json_t.age;
21+
}
22+
} // namespace ns
23+
24+
int main()
25+
{
26+
ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60};
27+
28+
// serialization: person -> json
29+
json j = p;
30+
std::cout << "serialization: " << j << std::endl;
31+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#include <iostream>
2+
#include <nlohmann/json.hpp>
3+
4+
using json = nlohmann::json;
5+
using namespace nlohmann::literals;
6+
7+
namespace ns
8+
{
9+
struct person
10+
{
11+
std::string name;
12+
std::string address;
13+
int age;
14+
};
15+
16+
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(person, name, address, age)
17+
} // namespace ns
18+
19+
int main()
20+
{
21+
ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60};
22+
23+
// serialization: person -> json
24+
json j = p;
25+
std::cout << "serialization: " << j << std::endl;
26+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"}

docs/mkdocs/docs/api/macros/index.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,11 @@ header. See also the [macro overview page](../../features/macros.md).
5050

5151
## Serialization/deserialization macros
5252

53-
- [**NLOHMANN_DEFINE_TYPE_INTRUSIVE(type, member...)**<br>**NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(type, member...)**][DefInt]
53+
- [**NLOHMANN_DEFINE_TYPE_INTRUSIVE(type, member...)**<br>**NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(type, member...)**
54+
<br>**NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(type, member...)**][DefInt]
5455
\- serialization/deserialization of types _with_ access to private variables
55-
- [**NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(type, member...)**<br>**NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(type, member...)**][DefNonInt]
56+
- [**NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(type, member...)**<br>**NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(type, member...)**
57+
<br>**NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(type, member...)**][DefNonInt]
5658
\- serialization/deserialization of types _without_ access to private variables
5759
- [**NLOHMANN_JSON_SERIALIZE_ENUM(type, ...)**](nlohmann_json_serialize_enum.md) - serialization/deserialization of enum types
5860

docs/mkdocs/docs/api/macros/nlohmann_define_type_intrusive.md

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
# NLOHMANN_DEFINE_TYPE_INTRUSIVE, NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT
1+
# NLOHMANN_DEFINE_TYPE_INTRUSIVE, NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT, NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE
22

33
```cpp
44
#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(type, member...) // (1)
55
#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(type, member...) // (2)
6+
#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(type, member...) // (3)
67
```
78
89
These macros can be used to simplify the serialization/deserialization of types if you want to use a JSON object as
@@ -16,6 +17,7 @@ parameter is the name of the class/struct, and all remaining parameters name the
1617
2. Will use [`value`](../basic_json/value.md) during deserialization and fall back to the default value for the
1718
respective type of the member variable if a key in the JSON object is missing. The generated `from_json()` function
1819
default constructs an object and uses its values as the defaults when calling the `value` function.
20+
3. Only defines the serialization. Useful in cases when the type does not have a default constructor and only serialization in required.
1921
2022
## Parameters
2123
@@ -31,7 +33,7 @@ The macros add two friend functions to the class which take care of the serializ
3133
3234
```cpp
3335
friend void to_json(nlohmann::json&, const type&);
34-
friend void from_json(const nlohmann::json&, type&);
36+
friend void from_json(const nlohmann::json&, type&); // except (3)
3537
```
3638

3739
See examples below for the concrete generated code.
@@ -40,7 +42,7 @@ See examples below for the concrete generated code.
4042

4143
!!! info "Prerequisites"
4244

43-
1. The type `type` must be default constructible. See [How can I use `get()` for non-default
45+
1. The type `type` must be default constructible (except (3)). See [How can I use `get()` for non-default
4446
constructible/non-copyable types?][GetNonDefNonCopy] for how to overcome this limitation.
4547
2. The macro must be used inside the type (class/struct).
4648

@@ -108,19 +110,47 @@ See examples below for the concrete generated code.
108110

109111
The macro is equivalent to:
110112

111-
```cpp hl_lines="21 22 23 24 25 26 27 28 29 30 31 32 33 34 35"
113+
```cpp hl_lines="22 23 24 25 26 27 28 29 30 31 32 33 34 35"
112114
--8<-- "examples/nlohmann_define_type_intrusive_with_default_explicit.cpp"
113115
```
114116

115117
Note how a default-initialized `person` object is used in the `from_json` to fill missing values.
116118

119+
??? example "Example (3): NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE"
120+
Consider the following complete example:
121+
122+
```cpp hl_lines="22"
123+
--8<-- "examples/nlohmann_define_type_intrusive_only_serialize_macro.cpp"
124+
```
125+
126+
Output:
127+
128+
```json
129+
--8<-- "examples/nlohmann_define_type_intrusive_only_serialize_macro.output"
130+
```
131+
132+
Notes:
133+
134+
- `ns::person` is non-default-constructible. This allows this macro to be used instead of
135+
`NLOHMANN_DEFINE_TYPE_INTRUSIVE` and `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT`.
136+
- `ns::person` has private member variables. This makes `NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE` applicable, but not
137+
`NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE`.
138+
- The macro `NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE` is used _inside_ the class.
139+
140+
The macro is equivalent to:
141+
142+
```cpp hl_lines="22 22 23 24 25 26 27"
143+
--8<-- "examples/nlohmann_define_type_intrusive_only_serialize_explicit.cpp"
144+
```
145+
117146
## See also
118147

119-
- [NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE / NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT](nlohmann_define_type_non_intrusive.md)
148+
- [NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE{_WITH_DEFAULT, _ONLY_SERIALIZE}](nlohmann_define_type_non_intrusive.md)
120149
for a similar macro that can be defined _outside_ the type.
121150
- [Arbitrary Type Conversions](../../features/arbitrary_types.md) for an overview.
122151

123152
## Version history
124153

125154
1. Added in version 3.9.0.
126155
2. Added in version 3.11.0.
156+
3. Added in version TODO.

0 commit comments

Comments
 (0)