-
-
Notifications
You must be signed in to change notification settings - Fork 6.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow custom base class as node customization point (#3110)
Co-authored-by: Niels Lohmann <niels.lohmann@gmail.com> Co-authored-by: Florian Albrechtskirchinger <falbrechtskirchinger@gmail.com> Co-authored-by: barcode <barcode@example.com>
- Loading branch information
1 parent
f7973f4
commit bed648c
Showing
12 changed files
with
595 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
#include <iostream> | ||
#include <nlohmann/json.hpp> | ||
|
||
class visitor_adaptor_with_metadata | ||
{ | ||
public: | ||
template <class Fnc> | ||
void visit(const Fnc& fnc) const; | ||
|
||
int metadata = 42; | ||
private: | ||
template <class Ptr, class Fnc> | ||
void do_visit(const Ptr& ptr, const Fnc& fnc) const; | ||
}; | ||
|
||
using json = nlohmann::basic_json < | ||
std::map, | ||
std::vector, | ||
std::string, | ||
bool, | ||
std::int64_t, | ||
std::uint64_t, | ||
double, | ||
std::allocator, | ||
nlohmann::adl_serializer, | ||
std::vector<std::uint8_t>, | ||
visitor_adaptor_with_metadata | ||
>; | ||
|
||
template <class Fnc> | ||
void visitor_adaptor_with_metadata::visit(const Fnc& fnc) const | ||
{ | ||
do_visit(json::json_pointer{}, fnc); | ||
} | ||
|
||
template <class Ptr, class Fnc> | ||
void visitor_adaptor_with_metadata::do_visit(const Ptr& ptr, const Fnc& fnc) const | ||
{ | ||
using value_t = nlohmann::detail::value_t; | ||
const json& j = *static_cast<const json*>(this); | ||
switch (j.type()) | ||
{ | ||
case value_t::object: | ||
fnc(ptr, j); | ||
for (const auto& entry : j.items()) | ||
{ | ||
entry.value().do_visit(ptr / entry.key(), fnc); | ||
} | ||
break; | ||
case value_t::array: | ||
fnc(ptr, j); | ||
for (std::size_t i = 0; i < j.size(); ++i) | ||
{ | ||
j.at(i).do_visit(ptr / std::to_string(i), fnc); | ||
} | ||
break; | ||
case value_t::null: | ||
case value_t::string: | ||
case value_t::boolean: | ||
case value_t::number_integer: | ||
case value_t::number_unsigned: | ||
case value_t::number_float: | ||
case value_t::binary: | ||
fnc(ptr, j); | ||
break; | ||
case value_t::discarded: | ||
default: | ||
break; | ||
} | ||
} | ||
|
||
int main() | ||
{ | ||
// create a json object | ||
json j; | ||
j["null"]; | ||
j["object"]["uint"] = 1U; | ||
j["object"].metadata = 21; | ||
|
||
// visit and output | ||
j.visit( | ||
[&](const json::json_pointer & p, | ||
const json & j) | ||
{ | ||
std::cout << (p.empty() ? std::string{"/"} : p.to_string()) | ||
<< " - metadata = " << j.metadata << " -> " << j.dump() << '\n'; | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
/ - metadata = 42 -> {"null":null,"object":{"uint":1}} | ||
/null - metadata = 42 -> null | ||
/object - metadata = 21 -> {"uint":1} | ||
/object/uint - metadata = 42 -> 1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# <small>nlohmann::basic_json::</small>json_base_class_t | ||
|
||
```cpp | ||
using json_base_class_t = detail::json_base_class<CustomBaseClass>; | ||
``` | ||
|
||
The base class used to inject custom functionality into each instance of `basic_json`. | ||
Examples of such functionality might be metadata, additional member functions (e.g., visitors), or other application-specific code. | ||
|
||
## Template parameters | ||
|
||
`CustomBaseClass` | ||
: the base class to be added to `basic_json` | ||
|
||
## Notes | ||
|
||
#### Default type | ||
|
||
The default value for `CustomBaseClass` is `void`. In this case an [empty base class](https://en.cppreference.com/w/cpp/language/ebo) is used and no additional functionality is injected. | ||
|
||
#### Limitations | ||
|
||
The type `CustomBaseClass` has to be a default-constructible class. | ||
`basic_json` only supports copy/move construction/assignment if `CustomBaseClass` does so as well. | ||
|
||
## Examples | ||
|
||
??? example | ||
|
||
The following code shows how to inject custom data and methods for each node. | ||
```cpp | ||
--8<-- "examples/json_base_class_t.cpp" | ||
``` | ||
|
||
Output: | ||
|
||
```json | ||
--8<-- "examples/json_base_class_t.output" | ||
``` | ||
|
||
## Version history | ||
|
||
- Added in version 3.12.0. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
#pragma once | ||
|
||
#include <type_traits> // conditional, is_same | ||
|
||
#include <nlohmann/detail/abi_macros.hpp> | ||
|
||
NLOHMANN_JSON_NAMESPACE_BEGIN | ||
namespace detail | ||
{ | ||
|
||
/*! | ||
@brief Default base class of the @ref basic_json class. | ||
So that the correct implementations of the copy / move ctors / assign operators | ||
of @ref basic_json do not require complex case distinctions | ||
(no base class / custom base class used as customization point), | ||
@ref basic_json always has a base class. | ||
By default, this class is used because it is empty and thus has no effect | ||
on the behavior of @ref basic_json. | ||
*/ | ||
struct json_default_base {}; | ||
|
||
template<class T> | ||
using json_base_class = typename std::conditional < | ||
std::is_same<T, void>::value, | ||
json_default_base, | ||
T | ||
>::type; | ||
|
||
} // namespace detail | ||
NLOHMANN_JSON_NAMESPACE_END |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.