89 lines
2.2 KiB
C++
89 lines
2.2 KiB
C++
|
#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';
|
||
|
});
|
||
|
}
|