-
-
Notifications
You must be signed in to change notification settings - Fork 7.1k
Allow custom base class as node customization point #3110
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
Merged
nlohmann
merged 35 commits into
nlohmann:develop
from
barcode:allow_custom_base_class_as_node_customization_point
Aug 28, 2022
Merged
Changes from 32 commits
Commits
Show all changes
35 commits
Select commit
Hold shift + click to select a range
143f868
Allow to add a custom base class as an extension point to json nodes
a131ecc
Fix code for msvc
51d8c28
Fix test
8f4d8a6
Re run make amalgamate
09f42fd
Suppress fals positive of cppcheck
e5534f1
Fix clang-tidy errors
0046348
Try fixing code for clang-tidy
ef54887
Remove make_unique to make the test c++11 compliant
e41e315
Add NOLINT since clang-tidy requests make_unique, but C++11 jobs don'…
f43c6b4
Document what the include of type_traits is used for
barcode 5204ebb
Add documentation
2e7e67d
Fix typo
barcode 500fc0a
Remove accidentally duplicated doc text
79a7056
Update / add documentation for custom base class
c427a52
Fix clang-tidy-15 warning about use after move
050a831
Update docs/mkdocs/docs/api/basic_json/json_base_class_t.md
barcode 21d0d38
Update docs/mkdocs/docs/api/basic_json/json_base_class_t.md
barcode 5539e6f
Update docs/mkdocs/docs/api/basic_json/json_base_class_t.md
barcode 0a8e16d
Adapt code to review
962fca2
readd suppress for cppcheck
7cd3033
run amalgamate
afb108a
Update include/nlohmann/detail/json_custom_base_class.hpp
barcode f516209
Update single_include/nlohmann/json.hpp
barcode 0bcc12c
Update include/nlohmann/detail/json_custom_base_class.hpp
barcode b1001c6
Update single_include/nlohmann/json.hpp
barcode 763c59d
Update docs/mkdocs/docs/api/basic_json/json_base_class_t.md
barcode 0ce9ded
Update docs/mkdocs/docs/api/basic_json/json_base_class_t.md
barcode 49ab721
Update docs/mkdocs/docs/api/basic_json/json_base_class_t.md
barcode b0f5baf
Update docs/mkdocs/docs/api/basic_json/json_base_class_t.md
barcode e9f5e0c
Update docs/mkdocs/docs/api/basic_json/json_base_class_t.md
barcode b3816f1
Update include/nlohmann/detail/json_custom_base_class.hpp
barcode 7d476a0
make amalgamate
c5ede1a
Update include/nlohmann/detail/json_custom_base_class.hpp
barcode 19423a7
make amalgamate
46597f0
Add include for nlohmann/detail/abi_macros.hpp
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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,29 @@ | ||
#pragma once | ||
|
||
#include <type_traits> // conditional, is_same | ||
|
||
NLOHMANN_JSON_NAMESPACE_BEGIN | ||
barcode marked this conversation as resolved.
Show resolved
Hide resolved
|
||
namespace detail | ||
{ | ||
|
||
/*! | ||
@brief Default base class of the @ref basic_json class. | ||
So that the correct implementation of the copy / move ctors / assign operators | ||
barcode marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
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> | ||
nlohmann marked this conversation as resolved.
Show resolved
Hide resolved
|
||
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 hidden or 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 hidden or 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 |
---|---|---|
|
@@ -47,6 +47,7 @@ | |
#include <nlohmann/detail/iterators/iteration_proxy.hpp> | ||
#include <nlohmann/detail/iterators/json_reverse_iterator.hpp> | ||
#include <nlohmann/detail/iterators/primitive_iterator.hpp> | ||
#include <nlohmann/detail/json_custom_base_class.hpp> | ||
#include <nlohmann/detail/json_pointer.hpp> | ||
#include <nlohmann/detail/json_ref.hpp> | ||
#include <nlohmann/detail/macro_scope.hpp> | ||
|
@@ -93,6 +94,7 @@ The invariants are checked by member function assert_invariant(). | |
*/ | ||
NLOHMANN_BASIC_JSON_TPL_DECLARATION | ||
class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) | ||
: public ::nlohmann::detail::json_base_class<CustomBaseClass> | ||
{ | ||
private: | ||
template<detail::value_t> friend struct detail::external_constructor; | ||
|
@@ -119,6 +121,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec | |
|
||
/// workaround type for MSVC | ||
using basic_json_t = NLOHMANN_BASIC_JSON_TPL; | ||
using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>; | ||
|
||
JSON_PRIVATE_UNLESS_TESTED: | ||
// convenience aliases for types residing in namespace detail; | ||
|
@@ -1132,7 +1135,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec | |
/// @brief copy constructor | ||
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/ | ||
basic_json(const basic_json& other) | ||
: m_type(other.m_type) | ||
: json_base_class_t(other), | ||
m_type(other.m_type) | ||
{ | ||
// check of passed value is valid | ||
other.assert_invariant(); | ||
|
@@ -1200,11 +1204,12 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec | |
/// @brief move constructor | ||
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/ | ||
basic_json(basic_json&& other) noexcept | ||
: m_type(std::move(other.m_type)), | ||
: json_base_class_t(std::move(other)), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @barcode Sorry for being so late, but now I got a warning from Clang-Tidy about accessing |
||
m_type(std::move(other.m_type)), | ||
m_value(std::move(other.m_value)) | ||
{ | ||
// check that passed value is valid | ||
other.assert_invariant(false); | ||
other.assert_invariant(false); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) | ||
|
||
// invalidate payload | ||
other.m_type = value_t::null; | ||
|
@@ -1220,7 +1225,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec | |
std::is_nothrow_move_constructible<value_t>::value&& | ||
std::is_nothrow_move_assignable<value_t>::value&& | ||
std::is_nothrow_move_constructible<json_value>::value&& | ||
std::is_nothrow_move_assignable<json_value>::value | ||
std::is_nothrow_move_assignable<json_value>::value&& | ||
std::is_nothrow_move_assignable<json_base_class_t>::value | ||
) | ||
{ | ||
// check that passed value is valid | ||
|
@@ -1229,6 +1235,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec | |
using std::swap; | ||
swap(m_type, other.m_type); | ||
swap(m_value, other.m_value); | ||
json_base_class_t::operator=(std::move(other)); | ||
|
||
set_parents(); | ||
assert_invariant(); | ||
|
This file contains hidden or 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.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.