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

Add serialization-only user defined type macros #3816

Merged
merged 7 commits into from
Nov 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#include <iostream>
#include <nlohmann/json.hpp>

using json = nlohmann::json;
using namespace nlohmann::literals;

namespace ns
{
class person
{
private:
std::string name = "John Doe";
std::string address = "123 Fake St";
int age = -1;

public:
// No default constructor
person(std::string name_, std::string address_, int age_)
: name(std::move(name_)), address(std::move(address_)), age(age_)
{}

friend void to_json(nlohmann::json& nlohmann_json_j, const person& nlohmann_json_t)
{
nlohmann_json_j["name"] = nlohmann_json_t.name;
nlohmann_json_j["address"] = nlohmann_json_t.address;
nlohmann_json_j["age"] = nlohmann_json_t.age;
}
};
} // namespace ns

int main()
{
ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60};

// serialization: person -> json
json j = p;
std::cout << "serialization: " << j << std::endl;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include <iostream>
#include <nlohmann/json.hpp>

using json = nlohmann::json;
using namespace nlohmann::literals;

namespace ns
{
class person
{
private:
std::string name = "John Doe";
std::string address = "123 Fake St";
int age = -1;

public:
// No default constructor
person(std::string name_, std::string address_, int age_)
: name(std::move(name_)), address(std::move(address_)), age(age_)
{}

NLOHMANN_DEFINE_TYPE_INTRUSIVE(person, name, address, age)
};
} // namespace ns

int main()
{
ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60};

// serialization: person -> json
json j = p;
std::cout << "serialization: " << j << std::endl;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include <iostream>
#include <nlohmann/json.hpp>

using json = nlohmann::json;
using namespace nlohmann::literals;

namespace ns
{
struct person
{
std::string name;
std::string address;
int age;
};

void to_json(nlohmann::json& nlohmann_json_j, const person& nlohmann_json_t)
{
nlohmann_json_j["name"] = nlohmann_json_t.name;
nlohmann_json_j["address"] = nlohmann_json_t.address;
nlohmann_json_j["age"] = nlohmann_json_t.age;
}
} // namespace ns

int main()
{
ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60};

// serialization: person -> json
json j = p;
std::cout << "serialization: " << j << std::endl;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include <iostream>
#include <nlohmann/json.hpp>

using json = nlohmann::json;
using namespace nlohmann::literals;

namespace ns
{
struct person
{
std::string name;
std::string address;
int age;
};

NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(person, name, address, age)
} // namespace ns

int main()
{
ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60};

// serialization: person -> json
json j = p;
std::cout << "serialization: " << j << std::endl;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"}
6 changes: 4 additions & 2 deletions docs/mkdocs/docs/api/macros/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,11 @@ header. See also the [macro overview page](../../features/macros.md).

## Serialization/deserialization macros

- [**NLOHMANN_DEFINE_TYPE_INTRUSIVE(type, member...)**<br>**NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(type, member...)**][DefInt]
- [**NLOHMANN_DEFINE_TYPE_INTRUSIVE(type, member...)**<br>**NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(type, member...)**
<br>**NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(type, member...)**][DefInt]
\- serialization/deserialization of types _with_ access to private variables
- [**NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(type, member...)**<br>**NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(type, member...)**][DefNonInt]
- [**NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(type, member...)**<br>**NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(type, member...)**
<br>**NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(type, member...)**][DefNonInt]
\- serialization/deserialization of types _without_ access to private variables
- [**NLOHMANN_JSON_SERIALIZE_ENUM(type, ...)**](nlohmann_json_serialize_enum.md) - serialization/deserialization of enum types

Expand Down
40 changes: 35 additions & 5 deletions docs/mkdocs/docs/api/macros/nlohmann_define_type_intrusive.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# NLOHMANN_DEFINE_TYPE_INTRUSIVE, NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT
# NLOHMANN_DEFINE_TYPE_INTRUSIVE, NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT, NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE

```cpp
#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(type, member...) // (1)
#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(type, member...) // (2)
#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(type, member...) // (3)
```

These macros can be used to simplify the serialization/deserialization of types if you want to use a JSON object as
Expand All @@ -16,6 +17,7 @@ parameter is the name of the class/struct, and all remaining parameters name the
2. Will use [`value`](../basic_json/value.md) during deserialization and fall back to the default value for the
respective type of the member variable if a key in the JSON object is missing. The generated `from_json()` function
default constructs an object and uses its values as the defaults when calling the `value` function.
3. Only defines the serialization. Useful in cases when the type does not have a default constructor and only serialization in required.

## Parameters

Expand All @@ -31,7 +33,7 @@ The macros add two friend functions to the class which take care of the serializ

```cpp
friend void to_json(nlohmann::json&, const type&);
friend void from_json(const nlohmann::json&, type&);
friend void from_json(const nlohmann::json&, type&); // except (3)
```

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

!!! info "Prerequisites"

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

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

The macro is equivalent to:

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

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

??? example "Example (3): NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE"
Consider the following complete example:

```cpp hl_lines="22"
--8<-- "examples/nlohmann_define_type_intrusive_only_serialize_macro.cpp"
```

Output:

```json
--8<-- "examples/nlohmann_define_type_intrusive_only_serialize_macro.output"
```

Notes:

- `ns::person` is non-default-constructible. This allows this macro to be used instead of
`NLOHMANN_DEFINE_TYPE_INTRUSIVE` and `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT`.
- `ns::person` has private member variables. This makes `NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE` applicable, but not
`NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE`.
- The macro `NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE` is used _inside_ the class.

The macro is equivalent to:

```cpp hl_lines="22 22 23 24 25 26 27"
--8<-- "examples/nlohmann_define_type_intrusive_only_serialize_explicit.cpp"
```

## See also

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

## Version history

1. Added in version 3.9.0.
2. Added in version 3.11.0.
3. Added in version TODO.
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE, NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT
# NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE, NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT, NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE

```cpp
#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(type, member...) // (1)
#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(type, member...) // (2)
#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(type, member...) // (3)
```

These macros can be used to simplify the serialization/deserialization of types if you want to use a JSON object as
Expand All @@ -16,6 +17,7 @@ parameter is the name of the class/struct, and all remaining parameters name the
2. Will use [`value`](../basic_json/value.md) during deserialization and fall back to the default value for the
respective type of the member variable if a key in the JSON object is missing. The generated `from_json()` function
default constructs an object and uses its values as the defaults when calling the `value` function.
3. Only defines the serialization. Useful in cases when the type does not have a default constructor and only serialization in required.

## Parameters

Expand All @@ -31,7 +33,7 @@ The macros add two functions to the namespace which take care of the serializati

```cpp
void to_json(nlohmann::json&, const type&);
void from_json(const nlohmann::json&, type&);
void from_json(const nlohmann::json&, type&); // except (3)
```

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

!!! info "Prerequisites"

1. The type `type` must be default constructible. See [How can I use `get()` for non-default constructible/non-copyable types?][GetNonDefNonCopy]
1. The type `type` must be default constructible (except (3). See [How can I use `get()` for non-default constructible/non-copyable types?][GetNonDefNonCopy]
for how to overcome this limitation.
2. The macro must be used outside the type (class/struct).
3. The passed members must be public.
Expand Down Expand Up @@ -88,7 +90,7 @@ See examples below for the concrete generated code.

Consider the following complete example:

```cpp hl_lines="21"
```cpp hl_lines="22"
--8<-- "examples/nlohmann_define_type_non_intrusive_with_default_macro.cpp"
```

Expand All @@ -109,19 +111,47 @@ See examples below for the concrete generated code.

The macro is equivalent to:

```cpp hl_lines="21 22 23 24 25 26 27 28 29 30 31 32 33 34"
```cpp hl_lines="22 23 24 25 26 27 28 29 30 31 32 33 34 35"
--8<-- "examples/nlohmann_define_type_non_intrusive_with_default_explicit.cpp"
```

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

??? example "Example (3): NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE"

Consider the following complete example:

```cpp hl_lines="16"
--8<-- "examples/nlohmann_define_type_non_intrusive_only_serialize_macro.cpp"
```

Output:

```json
--8<-- "examples/nlohmann_define_type_non_intrusive_only_serialize_macro.output"
```

Notes:

- `ns::person` is non-default-constructible. This allows this macro to be used instead of
`NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE` and `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT`.
- `ns::person` has only public member variables. This makes `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE` applicable.
- The macro `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE` is used _outside_ the class, but _inside_ its namespace `ns`.

The macro is equivalent to:

```cpp hl_lines="16 17 18 19 20 21"
--8<-- "examples/nlohmann_define_type_non_intrusive_only_serialize_explicit.cpp"
```

## See also

- [NLOHMANN_DEFINE_TYPE_INTRUSIVE / NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT](nlohmann_define_type_intrusive.md)
- [NLOHMANN_DEFINE_TYPE_INTRUSIVE{_WITH_DEFAULT, _ONLY_SERIALIZE}](nlohmann_define_type_intrusive.md)
for a similar macro that can be defined _inside_ the type.
- [Arbitrary Type Conversions](../../features/arbitrary_types.md) for an overview.

## Version history

1. Added in version 3.9.0.
2. Added in version 3.11.0.
3. Added in version TODO.
14 changes: 14 additions & 0 deletions docs/mkdocs/docs/features/macros.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,13 @@ an object and uses its values as the defaults when calling the [`value`](../api/

See [full documentation of `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT`](../api/macros/nlohmann_define_type_intrusive.md).

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

This macro is similar to `NLOHMANN_DEFINE_TYPE_INTRUSIVE` except that it defines only the serialization code. This is
useful when the user type does not have a default constructor and only the serialization is required.

See [full documentation of `NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE`](../api/macros//nlohmann_define_type_intrusive.md).

## `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
Expand All @@ -138,6 +145,13 @@ an object and uses its values as the defaults when calling the [`value`](../api/

See [full documentation of `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT`](../api/macros/nlohmann_define_type_non_intrusive.md).

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

This macro is similar to `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE` except that it defines only the serialization code. This is
useful when the user type does not have a default constructor and only the serialization is required.

See [full documentation of `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE`](../api/macros//nlohmann_define_type_non_intrusive.md).

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

This macro simplifies the serialization/deserialization of enum types. See
Expand Down
6 changes: 6 additions & 0 deletions include/nlohmann/detail/macro_scope.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,9 @@
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) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }

#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(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__)) }

/*!
@brief macro
@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
Expand All @@ -415,6 +418,9 @@
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_ONLY_SERIALIZE(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__)) }

#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) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
Expand Down
Loading
Loading