📝 complete macro documentation

This commit is contained in:
Niels Lohmann 2022-04-23 23:53:30 +02:00
parent 48af996d90
commit a1755a0b2b
No known key found for this signature in database
GPG Key ID: 7F3CEA63AE251B69
32 changed files with 874 additions and 36 deletions

View File

@ -0,0 +1,59 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
namespace ns
{
class person
{
private:
std::string name = "John Doe";
std::string address = "123 Fake St";
int age = -1;
public:
person() = default;
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;
}
friend void from_json(const nlohmann::json& nlohmann_json_j, person& nlohmann_json_t)
{
nlohmann_json_t.name = nlohmann_json_j.at("name");
nlohmann_json_t.address = nlohmann_json_j.at("address");
nlohmann_json_t.age = nlohmann_json_j.at("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;
// deserialization: json -> person
json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json;
auto p2 = j2.get<ns::person>();
// incomplete deserialization:
json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json;
try
{
auto p3 = j3.get<ns::person>();
}
catch (json::exception& e)
{
std::cout << "deserialization failed: " << e.what() << std::endl;
}
}

View File

@ -0,0 +1,2 @@
serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"}
deserialization failed: [json.exception.out_of_range.403] key 'age' not found

View File

@ -0,0 +1,47 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
namespace ns
{
class person
{
private:
std::string name = "John Doe";
std::string address = "123 Fake St";
int age = -1;
public:
person() = default;
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;
// deserialization: json -> person
json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json;
auto p2 = j2.get<ns::person>();
// incomplete deserialization:
json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json;
try
{
auto p3 = j3.get<ns::person>();
}
catch (json::exception& e)
{
std::cout << "deserialization failed: " << e.what() << std::endl;
}
}

View File

@ -0,0 +1,2 @@
serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"}
deserialization failed: [json.exception.out_of_range.403] key 'age' not found

View File

@ -0,0 +1,54 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
namespace ns
{
class person
{
private:
std::string name = "John Doe";
std::string address = "123 Fake St";
int age = -1;
public:
person() = default;
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;
}
friend void from_json(const nlohmann::json& nlohmann_json_j, person& nlohmann_json_t)
{
person nlohmann_json_default_obj;
nlohmann_json_t.name = nlohmann_json_j.value("name", nlohmann_json_default_obj.name);
nlohmann_json_t.address = nlohmann_json_j.value("address", nlohmann_json_default_obj.address);
nlohmann_json_t.age = nlohmann_json_j.value("age", nlohmann_json_default_obj.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;
// deserialization: json -> person
json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json;
auto p2 = j2.get<ns::person>();
// incomplete deserialization:
json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json;
auto p3 = j3.get<ns::person>();
std::cout << "roundtrip: " << json(p3) << std::endl;
}

View File

@ -0,0 +1,2 @@
serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"}
roundtrip: {"address":"742 Evergreen Terrace","age":-1,"name":"Maggie Simpson"}

View File

@ -0,0 +1,41 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
namespace ns
{
class person
{
private:
std::string name = "John Doe";
std::string address = "123 Fake St";
int age = -1;
public:
person() = default;
person(std::string name_, std::string address_, int age_)
: name(std::move(name_)), address(std::move(address_)), age(age_)
{}
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(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;
// deserialization: json -> person
json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json;
auto p2 = j2.get<ns::person>();
// incomplete deserialization:
json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json;
auto p3 = j3.get<ns::person>();
std::cout << "roundtrip: " << json(p3) << std::endl;
}

View File

@ -0,0 +1,2 @@
serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"}
roundtrip: {"address":"742 Evergreen Terrace","age":-1,"name":"Maggie Simpson"}

View File

@ -0,0 +1,52 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
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;
}
void from_json(const nlohmann::json& nlohmann_json_j, person& nlohmann_json_t)
{
nlohmann_json_t.name = nlohmann_json_j.at("name");
nlohmann_json_t.address = nlohmann_json_j.at("address");
nlohmann_json_t.age = nlohmann_json_j.at("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;
// deserialization: json -> person
json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json;
auto p2 = j2.get<ns::person>();
// incomplete deserialization:
json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json;
try
{
auto p3 = j3.get<ns::person>();
}
catch (json::exception& e)
{
std::cout << "deserialization failed: " << e.what() << std::endl;
}
}

View File

@ -0,0 +1,2 @@
serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"}
deserialization failed: [json.exception.out_of_range.403] key 'age' not found

View File

@ -0,0 +1,40 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
namespace ns
{
struct person
{
std::string name;
std::string address;
int age;
};
NLOHMANN_DEFINE_TYPE_NON_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;
// deserialization: json -> person
json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json;
auto p2 = j2.get<ns::person>();
// incomplete deserialization:
json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json;
try
{
auto p3 = j3.get<ns::person>();
}
catch (json::exception& e)
{
std::cout << "deserialization failed: " << e.what() << std::endl;
}
}

View File

@ -0,0 +1,2 @@
serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"}
deserialization failed: [json.exception.out_of_range.403] key 'age' not found

View File

@ -0,0 +1,52 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
namespace ns
{
struct person
{
std::string name = "John Doe";
std::string address = "123 Fake St";
int age = -1;
person() = default;
person(std::string name_, std::string address_, int age_)
: name(std::move(name_)), address(std::move(address_)), age(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;
}
void from_json(const nlohmann::json& nlohmann_json_j, person& nlohmann_json_t)
{
person nlohmann_json_default_obj;
nlohmann_json_t.name = nlohmann_json_j.value("name", nlohmann_json_default_obj.name);
nlohmann_json_t.address = nlohmann_json_j.value("address", nlohmann_json_default_obj.address);
nlohmann_json_t.age = nlohmann_json_j.value("age", nlohmann_json_default_obj.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;
// deserialization: json -> person
json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json;
auto p2 = j2.get<ns::person>();
// incomplete deserialization:
json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json;
auto p3 = j3.get<ns::person>();
std::cout << "roundtrip: " << json(p3) << std::endl;
}

View File

@ -0,0 +1,2 @@
serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"}
roundtrip: {"address":"742 Evergreen Terrace","age":-1,"name":"Maggie Simpson"}

View File

@ -0,0 +1,39 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
namespace ns
{
struct person
{
std::string name = "John Doe";
std::string address = "123 Fake St";
int age = -1;
person() = default;
person(std::string name_, std::string address_, int age_)
: name(std::move(name_)), address(std::move(address_)), age(age_)
{}
};
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(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;
// deserialization: json -> person
json j2 = R"({"address": "742 Evergreen Terrace", "age": 40, "name": "Homer Simpson"})"_json;
auto p2 = j2.get<ns::person>();
// incomplete deserialization:
json j3 = R"({"address": "742 Evergreen Terrace", "name": "Maggie Simpson"})"_json;
auto p3 = j3.get<ns::person>();
std::cout << "roundtrip: " << json(p3) << std::endl;
}

View File

@ -0,0 +1,2 @@
serialization: {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"}
roundtrip: {"address":"742 Evergreen Terrace","age":-1,"name":"Maggie Simpson"}

View File

@ -0,0 +1,59 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
namespace ns
{
enum TaskState
{
TS_STOPPED,
TS_RUNNING,
TS_COMPLETED,
TS_INVALID = -1
};
NLOHMANN_JSON_SERIALIZE_ENUM(TaskState,
{
{ TS_INVALID, nullptr },
{ TS_STOPPED, "stopped" },
{ TS_RUNNING, "running" },
{ TS_COMPLETED, "completed" }
})
enum class Color
{
red, green, blue, unknown
};
NLOHMANN_JSON_SERIALIZE_ENUM(Color,
{
{ Color::unknown, "unknown" }, { Color::red, "red" },
{ Color::green, "green" }, { Color::blue, "blue" }
})
} // namespace ns
int main()
{
// serialization
json j_stopped = ns::TS_STOPPED;
json j_red = ns::Color::red;
std::cout << "ns::TS_STOPPED -> " << j_stopped
<< ", ns::Color::red -> " << j_red << std::endl;
// deserialization
json j_running = "running";
json j_blue = "blue";
auto running = j_running.get<ns::TaskState>();
auto blue = j_blue.get<ns::Color>();
std::cout << j_running << " -> " << running
<< ", " << j_blue << " -> " << static_cast<int>(blue) << std::endl;
// deserializing undefined JSON value to enum
// (where the first map entry above is the default)
json j_pi = 3.14;
auto invalid = j_pi.get<ns::TaskState>();
auto unknown = j_pi.get<ns::Color>();
std::cout << j_pi << " -> " << invalid << ", "
<< j_pi << " -> " << static_cast<int>(unknown) << std::endl;
}

View File

@ -0,0 +1,3 @@
ns::TS_STOPPED -> "stopped", ns::Color::red -> "red"
"running" -> 1, "blue" -> 2
3.14 -> -1, 3.14 -> 3

View File

@ -0,0 +1,33 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
namespace ns
{
enum class Color
{
red, green, blue, unknown
};
NLOHMANN_JSON_SERIALIZE_ENUM(Color,
{
{ Color::unknown, "unknown" }, { Color::red, "red" },
{ Color::green, "green" }, { Color::blue, "blue" },
{ Color::red, "rot" } // a second conversion for Color::red
})
}
int main()
{
// serialization
json j_red = ns::Color::red;
std::cout << static_cast<int>(ns::Color::red) << " -> " << j_red << std::endl;
// deserialization
json j_rot = "rot";
auto rot = j_rot.get<ns::Color>();
auto red = j_red.get<ns::Color>();
std::cout << j_rot << " -> " << static_cast<int>(rot) << std::endl;
std::cout << j_red << " -> " << static_cast<int>(red) << std::endl;
}

View File

@ -0,0 +1,3 @@
0 -> "red"
"rot" -> 0
"red" -> 0

View File

@ -2,6 +2,9 @@
serve: prepare_files serve: prepare_files
venv/bin/mkdocs serve venv/bin/mkdocs serve
serve_dirty: prepare_files
venv/bin/mkdocs serve --dirtyreload
build: prepare_files build: prepare_files
venv/bin/mkdocs build venv/bin/mkdocs build

View File

@ -1,11 +1,7 @@
# Macros # Macros
!!! note
This page is under construction. See the [macro overview page](../../features/macros.md) until then.
Some aspects of the library can be configured by defining preprocessor macros **before** including the `json.hpp` Some aspects of the library can be configured by defining preprocessor macros **before** including the `json.hpp`
header. header. See also the [macro overview page](../../features/macros.md).
## Runtime assertions ## Runtime assertions
@ -35,6 +31,7 @@ header.
## Serialization/deserialization macros ## Serialization/deserialization macros
- `NLOHMANN_DEFINE_TYPE_INTRUSIVE(type, member...)` - [**NLOHMANN_DEFINE_TYPE_INTRUSIVE(type, member...)**<br>**NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(type, member...)**](nlohmann_define_type_intrusive.md) - serialization/deserialization of types _with_ access to private variables
- `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(type, member...)` - [**NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(type, member...)**<br>**NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(type, member...)**](nlohmann_define_type_non_intrusive.md) - serialization/deserialization of types _without_ access to private variables
- `NLOHMANN_JSON_SERIALIZE_ENUM(type, ...)` - [**NLOHMANN_JSON_SERIALIZE_ENUM(type, ...)**](nlohmann_json_serialize_enum.md) - serialization/deserialization of enum
types

View File

@ -1,4 +1,4 @@
# JSON_ASSERT(x) # JSON_ASSERT
```cpp ```cpp
#define JSON_ASSERT(x) /* value */ #define JSON_ASSERT(x) /* value */

View File

@ -1,4 +1,4 @@
# JSON_CATCH_USER(exception), JSON_THROW_USER(exception), JSON_TRY_USER # JSON_CATCH_USER, JSON_THROW_USER, JSON_TRY_USER
```cpp ```cpp
// (1) // (1)
@ -20,6 +20,11 @@ Controls how exceptions are handled by the library.
undefined behavior. undefined behavior.
3. This macro overrides `#!cpp try` calls inside the library. It has no arguments and is always followed by a scope. 3. This macro overrides `#!cpp try` calls inside the library. It has no arguments and is always followed by a scope.
## Parameters
`exception` (in)
: an exception type
## Default definition ## Default definition
By default, the macros map to their respective C++ keywords: By default, the macros map to their respective C++ keywords:

View File

@ -0,0 +1,124 @@
# NLOHMANN_DEFINE_TYPE_INTRUSIVE, NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT
```cpp
#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(type, member...) // (1)
#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(type, member...) // (2)
```
These macros can be used to simplify the serialization/deserialization of types if you want to use a JSON object as
serialization and want to user the member variable names as object keys in that object. The macro is to be defined
**inside** the class/struct to create code for.
Unlike [`NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`](nlohmann_define_type_non_intrusive.md), it can access private members.
The first parameter is the name of the class/struct, and all remaining parameters name the members.
1. Will use [`at`](../basic_json/at.md) during deserialization and will throw
[`out_of_range.403`](../../home/exceptions.md#jsonexceptionout_of_range403) if a key is missing in the JSON object.
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.
## Parameters
`type` (in)
: name of the type (class, struct) to serialize/deserialize
`member` (in)
: name of the member variable to serialize/deserialize; up to 64 members can be given as comma-separated list
## Default definition
The macros add two friend functions to the class which take care of the serialization and deserialization:
```cpp
friend void to_json(nlohmann::json&, const type&);
friend void from_json(const nlohmann::json&, type&);
```
See examples below for the concrete generated code.
## Notes
!!! info "Prerequisites"
1. The type `type` must be default constructible. See [How can I use `get()` for non-default constructible/non-copyable types?](../../features/arbitrary_types.md#how-can-i-use-get-for-non-default-constructiblenon-copyable-types)
for how to overcome this limitation.
2. The macro must be used inside the type (class/struct).
!!! warning "Implementation limits"
- The current implementation is limited to at most 64 member variables. If you want to serialize/deserialize types
with more than 64 member variables, you need to define the `to_json`/`from_json` functions manually.
- The macros only work for the [`nlohmann::json`](../json.md) type; other specializations such as
[`nlohmann::ordered_json`](../ordered_json.md) are currently unsupported.
## Examples
??? example "Example (1): NLOHMANN_DEFINE_TYPE_INTRUSIVE"
Consider the following complete example:
```cpp hl_lines="21"
--8<-- "examples/nlohmann_define_type_intrusive_macro.cpp"
```
Output:
```json
--8<-- "examples/nlohmann_define_type_intrusive_macro.output"
```
Notes:
- `ns::person` is default-constructible. This is a requirement for using the macro.
- `ns::person` has private member variables. This makes `NLOHMANN_DEFINE_TYPE_INTRUSIVE` applicable, but not
`NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`.
- The macro `NLOHMANN_DEFINE_TYPE_INTRUSIVE` is used _inside_ the class.
- A missing key "age" in the deserialization yields an exception. To fall back to the default value,
`NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT` can be used.
The macro is equivalent to:
```cpp hl_lines="21 22 23 24 25 26 27 28 29 30 31 32 33"
--8<-- "examples/nlohmann_define_type_intrusive_explicit.cpp"
```
??? example "Example (2): NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT"
Consider the following complete example:
```cpp hl_lines="21"
--8<-- "examples/nlohmann_define_type_intrusive_with_default_macro.cpp"
```
Output:
```json
--8<-- "examples/nlohmann_define_type_intrusive_with_default_macro.output"
```
Notes:
- `ns::person` is default-constructible. This is a requirement for using the macro.
- `ns::person` has private member variables. This makes `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT` applicable,
but not `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT`.
- The macro `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT` is used _inside_ the class.
- A missing key "age" in the deserialization does not yield an exception. Instead, the default value `-1` is used.
The macro is equivalent to:
```cpp hl_lines="21 22 23 24 25 26 27 28 29 30 31 32 33 34"
--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.
## See also
- [NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE / NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT](nlohmann_define_type_non_intrusive.md)
for a similar macro that can be defined _outside_ the type.
- [Arbitrary Types Conversions](../../features/arbitrary_types.md) for an overview.
## Version history
1. Added in version 3.9.0.
2. Added in version 3.11.0.

View File

@ -0,0 +1,124 @@
# NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE, NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT
```cpp
#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(type, member...) // (1)
#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(type, member...) // (2)
```
These macros can be used to simplify the serialization/deserialization of types if you want to use a JSON object as
serialization and want to user the member variable names as object keys in that object. The macro is to be defined
**outside** the class/struct to create code for, but **inside** its namespace.
Unlike [`NLOHMANN_DEFINE_TYPE_INTRUSIVE`](nlohmann_define_type_intrusive.md), it **cannot** access private members.
The first parameter is the name of the class/struct, and all remaining parameters name the members.
1. Will use [`at`](../basic_json/at.md) during deserialization and will throw
[`out_of_range.403`](../../home/exceptions.md#jsonexceptionout_of_range403) if a key is missing in the JSON object.
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.
## Parameters
`type` (in)
: name of the type (class, struct) to serialize/deserialize
`member` (in)
: name of the (public) member variable to serialize/deserialize; up to 64 members can be given as comma-separated list
## Default definition
The macros add two functions to the namespace which take care of the serialization and deserialization:
```cpp
void to_json(nlohmann::json&, const type&);
void from_json(const nlohmann::json&, type&);
```
See examples below for the concrete generated code.
## Notes
!!! info "Prerequisites"
1. The type `type` must be default constructible. See [How can I use `get()` for non-default constructible/non-copyable types?](../../features/arbitrary_types.md#how-can-i-use-get-for-non-default-constructiblenon-copyable-types)
for how to overcome this limitation.
2. The macro must be used outside the type (class/struct).
3. The passed members must be public.
!!! warning "Implementation limit"
- The current implementation is limited to at most 64 member variables. If you want to serialize/deserialize types
with more than 64 member variables, you need to define the `to_json`/`from_json` functions manually.
- The macros only work for the [`nlohmann::json`](../json.md) type; other specializations such as
[`nlohmann::ordered_json`](../ordered_json.md) are currently unsupported.
## Examples
??? example "Example (1): NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE"
Consider the following complete example:
```cpp hl_lines="15"
--8<-- "examples/nlohmann_define_type_non_intrusive_macro.cpp"
```
Output:
```json
--8<-- "examples/nlohmann_define_type_non_intrusive_macro.output"
```
Notes:
- `ns::person` is default-constructible. This is a requirement for using the macro.
- `ns::person` has only public member variables. This makes `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE` applicable.
- The macro `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE` is used _outside_ the class, but _inside_ its namespace `ns`.
- A missing key "age" in the deserialization yields an exception. To fall back to the default value,
`NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT` can be used.
The macro is equivalent to:
```cpp hl_lines="15 16 17 18 19 20 21 22 23 24 25 26 27"
--8<-- "examples/nlohmann_define_type_non_intrusive_explicit.cpp"
```
??? example "Example (2): NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT"
Consider the following complete example:
```cpp hl_lines="20"
--8<-- "examples/nlohmann_define_type_non_intrusive_with_default_macro.cpp"
```
Output:
```json
--8<-- "examples/nlohmann_define_type_non_intrusive_with_default_macro.output"
```
Notes:
- `ns::person` is default-constructible. This is a requirement for using the macro.
- `ns::person` has only public member variables. This makes `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT`
applicable.
- The macro `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT` is used _outside_ the class, but _inside_ its namespace `ns`.
- A missing key "age" in the deserialization does not yield an exception. Instead, the default value `-1` is used.
The macro is equivalent to:
```cpp hl_lines="20 21 22 23 24 25 26 27 28 29 30 31 32 33"
--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.
## See also
- [NLOHMANN_DEFINE_TYPE_INTRUSIVE / NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT](nlohmann_define_type_intrusive.md)
for a similar macro that can be defined _inside_ the type.
- [Arbitrary Types Conversions](../../features/arbitrary_types.md) for an overview.
## Version history
1. Added in version 3.9.0.
2. Added in version 3.11.0.

View File

@ -0,0 +1,84 @@
# NLOHMANN_JSON_SERIALIZE_ENUM
```cpp
#define NLOHMANN_JSON_SERIALIZE_ENUM(type, conversion...)
```
By default, enum values are serialized to JSON as integers. In some cases this could result in undesired behavior. If an
enum is modified or re-ordered after data has been serialized to JSON, the later de-serialized JSON data may be
undefined or a different enum value than was originally intended.
The `NLOHMANN_JSON_SERIALIZE_ENUM` allows to define a user-defined serialization for every enumerator.
## Parameters
`type` (in)
: name of the enum to serialize/deserialize
`conversion` (in)
: a pair of an enumerator and a JSON serialization; arbitrary pairs can can be given as comma-separated list
## Default definition
The macros add two friend functions to the class which take care of the serialization and deserialization:
```cpp
template<typename BasicJsonType>
inline void to_json(BasicJsonType& j, const type& e);
template<typename BasicJsonType>
inline void from_json(const BasicJsonType& j, type& e);
```
## Notes
!!! info "Prerequisites"
The macro must be used inside the namespace of the enum.
!!! important "Important notes"
- When using [`get<ENUM_TYPE>()`](../basic_json/get.md), undefined JSON values will default to the first specified
conversion. Select this default pair carefully. See example 1 below.
- If an enum or JSON value is specified in multiple conversions, the first matching conversion from the top of the
list will be returned when converting to or from JSON. See example 2 below.
## Examples
??? example "Example 1: Basic usage"
The example shows how `NLOHMANN_JSON_SERIALIZE_ENUM` can be used to serialize/deserialize both classical enums and
C++11 enum classes:
```cpp hl_lines="16 17 18 19 20 21 22 29 30 31 32 33"
--8<-- "examples/nlohmann_json_serialize_enum.cpp"
```
Output:
```json
--8<-- "examples/nlohmann_json_serialize_enum.output"
```
??? example "Example 2: Multiple conversions for one enumerator"
The example shows how to use multiple conversions for a single enumerator. In the example, `Color::red` will always
be *serialized* to `"red"`, because the first occurring conversion. The second conversion, however, offers an
alternative *deserialization* from `"rot"` to `Color::red`.
```cpp hl_lines="17"
--8<-- "examples/nlohmann_json_serialize_enum_2.cpp"
```
Output:
```json
--8<-- "examples/nlohmann_json_serialize_enum_2.output"
```
## See also
- [Specializing enum conversion](../../features/enum_conversion.md)
## Version history
Added in version 3.4.0.

View File

@ -87,14 +87,14 @@ If you just want to serialize/deserialize some structs, the `to_json`/`from_json
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: 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 the namespace of the class/struct to create code for. It will throw an exception in `from_json()` due to a missing value in the JSON object. - [`NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(name, member1, member2, ...)`](../api/macros/nlohmann_define_type_non_intrusive.md) is to be defined inside the namespace of the class/struct to create code for. It will throw an exception in `from_json()` due to a missing value in the JSON object.
- `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(name, member1, member2, ...)` is to be defined inside the namespace of the class/struct to create code for. It will not throw an exception in `from_json()` due to a missing value in the JSON object, but fills in values from object which is default-constructed by the type. - [`NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(name, member1, member2, ...)`](../api/macros/nlohmann_define_type_non_intrusive.md) is to be defined inside the namespace of the class/struct to create code for. It will not throw an exception in `from_json()` due to a missing value in the JSON object, but fills in values from object which is default-constructed by the type.
- `NLOHMANN_DEFINE_TYPE_INTRUSIVE(name, member1, member2, ...)` is to be defined inside the class/struct to create code for. This macro can also access private members. It will throw an exception in `from_json()` due to a missing value in the JSON object. - [`NLOHMANN_DEFINE_TYPE_INTRUSIVE(name, member1, member2, ...)`](../api/macros/nlohmann_define_type_intrusive.md) is to be defined inside the class/struct to create code for. This macro can also access private members. It will throw an exception in `from_json()` due to a missing value in the JSON object.
- `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(name, member1, member2, ...)` is to be defined inside the class/struct to create code for. This macro can also access private members. It will not throw an exception in `from_json()` due to a missing value in the JSON object, but fills in values from object which is default-constructed by the type. - [`NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(name, member1, member2, ...)`](../api/macros/nlohmann_define_type_intrusive.md) is to be defined inside the class/struct to create code for. This macro can also access private members. It will not throw an exception in `from_json()` due to a missing value in the JSON object, but fills in values from object which is default-constructed by the type.
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). 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 !!! info "Implementation limit"
At most 64 member variables can be passed to these macros. At most 64 member variables can be passed to these macros.

View File

@ -24,8 +24,8 @@ NLOHMANN_JSON_SERIALIZE_ENUM( TaskState, {
}) })
``` ```
The `NLOHMANN_JSON_SERIALIZE_ENUM()` macro declares a set of `to_json()` / `from_json()` functions for type `TaskState` The [`NLOHMANN_JSON_SERIALIZE_ENUM()` macro](../api/macros/nlohmann_json_serialize_enum.md) declares a set of
while avoiding repetition and boilerplate serialization code. `to_json()` / `from_json()` functions for type `TaskState` while avoiding repetition and boilerplate serialization code.
## Usage ## Usage
@ -45,10 +45,11 @@ assert(jPi.get<TaskState>() == TS_INVALID );
## Notes ## Notes
Just as in [Arbitrary Type Conversions](#arbitrary-types-conversions) above, Just as in [Arbitrary Type Conversions](arbitrary_types.md) above,
- `NLOHMANN_JSON_SERIALIZE_ENUM()` MUST be declared in your enum type's namespace (which can be the global namespace), - [`NLOHMANN_JSON_SERIALIZE_ENUM()`](../api/macros/nlohmann_json_serialize_enum.md) MUST be declared in your enum type's
or the library will not be able to locate it, and it will default to integer serialization. namespace (which can be the global namespace), or the library will not be able to locate it, and it will default to
integer serialization.
- It MUST be available (e.g., proper headers must be included) everywhere you use the conversions. - It MUST be available (e.g., proper headers must be included) everywhere you use the conversions.
Other Important points: Other Important points:

View File

@ -1,6 +1,7 @@
# Supported Macros # Supported Macros
Some aspects of the library can be configured by defining preprocessor macros before including the `json.hpp` header. Some aspects of the library can be configured by defining preprocessor macros before including the `json.hpp` header.
See also the [API documentation for macros](../api/macros/index.md) for examples and more information.
## `JSON_ASSERT(x)` ## `JSON_ASSERT(x)`
@ -102,18 +103,15 @@ The macro is to be defined inside the class/struct to create code for. Unlike
[`NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`](#nlohmann_define_type_non_intrusivetype-member), it can access private members. [`NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`](#nlohmann_define_type_non_intrusivetype-member), it can access private members.
The first parameter is the name of the class/struct, and all remaining parameters name the members. The first parameter is the name of the class/struct, and all remaining parameters name the members.
See [Simplify your life with macros](arbitrary_types.md#simplify-your-life-with-macros) for an example. See [full documentation of `NLOHMANN_DEFINE_TYPE_INTRUSIVE`](../api/macros/nlohmann_define_type_intrusive.md).
The macro was introduced in version 3.9.0.
## `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(type, member...)` ## `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 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 missing value in the JSON object, but can throw due to a mismatched type. The `from_json()` function default constructs
type be default constructible. The `from_json()` function default constructs an object and uses its values as the an object and uses its values as the defaults when calling the [`value`](../api/basic_json/value.md) function.
defaults when calling the `value()` function.
The macro was introduced in version 3.11.0. See [full documentation of `NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT`](../api/macros/nlohmann_define_type_intrusive.md).
## `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(type, member...)` ## `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(type, member...)`
@ -124,25 +122,22 @@ The macro is to be defined inside the namespace of the class/struct to create co
accessed. Use [`NLOHMANN_DEFINE_TYPE_INTRUSIVE`](#nlohmann_define_type_intrusivetype-member) in these scenarios. The accessed. Use [`NLOHMANN_DEFINE_TYPE_INTRUSIVE`](#nlohmann_define_type_intrusivetype-member) in these scenarios. The
first parameter is the name of the class/struct, and all remaining parameters name the members. first parameter is the name of the class/struct, and all remaining parameters name the members.
See [Simplify your life with macros](arbitrary_types.md#simplify-your-life-with-macros) for an example. See [full documentation of `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE`](../api/macros/nlohmann_define_type_non_intrusive.md).
The macro was introduced in version 3.9.0.
## `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(type, member...)` ## `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 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 missing value in the JSON object, but can throw due to a mismatched type. The `from_json()` function default constructs
type be default constructible. The `from_json()` function default constructs an object and uses its values as the an object and uses its values as the defaults when calling the [`value`](../api/basic_json/value.md) function.
defaults when calling the `value()` function.
The macro was introduced in version 3.11.0. See [full documentation of `NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT`](../api/macros/nlohmann_define_type_non_intrusive.md).
## `NLOHMANN_JSON_SERIALIZE_ENUM(type, ...)` ## `NLOHMANN_JSON_SERIALIZE_ENUM(type, ...)`
This macro simplifies the serialization/deserialization of enum types. See This macro simplifies the serialization/deserialization of enum types. See
[Specializing enum conversion](enum_conversion.md) for more information. [Specializing enum conversion](enum_conversion.md) for more information.
The macro was introduced in version 3.4.0. See [full documentation of `NLOHMANN_JSON_SERIALIZE_ENUM`](../api/macros/nlohmann_json_serialize_enum.md).
## `NLOHMANN_JSON_VERSION_MAJOR`, `NLOHMANN_JSON_VERSION_MINOR`, `NLOHMANN_JSON_VERSION_PATCH` ## `NLOHMANN_JSON_VERSION_MAJOR`, `NLOHMANN_JSON_VERSION_MINOR`, `NLOHMANN_JSON_VERSION_PATCH`

View File

@ -233,7 +233,7 @@ nav:
- 'ordered_map': api/ordered_map.md - 'ordered_map': api/ordered_map.md
- macros: - macros:
- 'Overview': api/macros/index.md - 'Overview': api/macros/index.md
- 'JSON_ASSERT(x)': api/macros/json_assert.md - 'JSON_ASSERT': api/macros/json_assert.md
- 'JSON_CATCH_USER': api/macros/json_throw_user.md - 'JSON_CATCH_USER': api/macros/json_throw_user.md
- 'JSON_DIAGNOSTICS': api/macros/json_diagnostics.md - 'JSON_DIAGNOSTICS': api/macros/json_diagnostics.md
- 'JSON_HAS_CPP_11': api/macros/json_has_cpp_11.md - 'JSON_HAS_CPP_11': api/macros/json_has_cpp_11.md
@ -249,6 +249,11 @@ nav:
- 'JSON_THROW_USER': api/macros/json_throw_user.md - 'JSON_THROW_USER': api/macros/json_throw_user.md
- 'JSON_TRY_USER': api/macros/json_throw_user.md - 'JSON_TRY_USER': api/macros/json_throw_user.md
- 'JSON_USE_IMPLICIT_CONVERSIONS': api/macros/json_use_implicit_conversions.md - 'JSON_USE_IMPLICIT_CONVERSIONS': api/macros/json_use_implicit_conversions.md
- 'NLOHMANN_DEFINE_TYPE_INTRUSIVE': api/macros/nlohmann_define_type_intrusive.md
- 'NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT': api/macros/nlohmann_define_type_intrusive.md
- 'NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE': api/macros/nlohmann_define_type_non_intrusive.md
- 'NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT': api/macros/nlohmann_define_type_non_intrusive.md
- 'NLOHMANN_JSON_SERIALIZE_ENUM': api/macros/nlohmann_json_serialize_enum.md
- 'NLOHMANN_JSON_VERSION_MAJOR': api/macros/nlohmann_json_version_major.md - 'NLOHMANN_JSON_VERSION_MAJOR': api/macros/nlohmann_json_version_major.md
- 'NLOHMANN_JSON_VERSION_MINOR': api/macros/nlohmann_json_version_major.md - 'NLOHMANN_JSON_VERSION_MINOR': api/macros/nlohmann_json_version_major.md
- 'NLOHMANN_JSON_VERSION_PATCH': api/macros/nlohmann_json_version_major.md - 'NLOHMANN_JSON_VERSION_PATCH': api/macros/nlohmann_json_version_major.md
@ -308,6 +313,7 @@ plugins:
lang: en lang: en
- minify: - minify:
minify_html: true minify_html: true
- git-revision-date-localized
extra_javascript: extra_javascript:
- https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-MML-AM_CHTML - https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-MML-AM_CHTML

View File

@ -16,6 +16,7 @@ mkdocs-material>=5.2.1
mkdocs-material-extensions>=1.0 mkdocs-material-extensions>=1.0
mkdocs-minify-plugin>=0.3.0 mkdocs-minify-plugin>=0.3.0
mkdocs-simple-hooks>=0.1.1 mkdocs-simple-hooks>=0.1.1
mkdocs-git-revision-date-localized-plugin>=1.0.1
nltk>=3.5 nltk>=3.5
plantuml>=0.3.0 plantuml>=0.3.0
plantuml-markdown>=3.2.2 plantuml-markdown>=3.2.2