#pragma once #include #include #include #include #include #include #include namespace jvalidate::adapter { template class JsonCppAdapter; template <> struct AdapterTraits { template using Adapter = adapter::JsonCppAdapter; using ConstAdapter = adapter::JsonCppAdapter; static Json::Value const & const_empty() { static Json::Value const g_value; return g_value; } }; template class JsonCppObjectAdapter : public detail::SimpleObjectAdapter { public: using JsonCppObjectAdapter::SimpleObjectAdapter::SimpleObjectAdapter; bool contains(std::string const & key) const { return this->const_value().isMember(key); } JsonCppAdapter operator[](std::string const & key) const { return this->value() ? &(*this->value())[key] : nullptr; } void assign(std::string const & key, Const const & frozen) const requires(not std::is_const_v) { (*this)[key].assign(frozen); } }; template class JsonCppAdapter final : public detail::SimpleAdapter { public: using JsonCppAdapter::SimpleAdapter::SimpleAdapter; Type type() const { switch (const_value().type()) { case Json::nullValue: return Type::Null; case Json::booleanValue: return Type::Boolean; case Json::realValue: if (Adapter::is_integer(as_number())) { return Type::Integer; } return Type::Number; case Json::stringValue: return Type::String; case Json::arrayValue: return Type::Array; case Json::objectValue: return Type::Object; case Json::intValue: case Json::uintValue: return Type::Integer; } } bool as_boolean() const { return const_value().asBool(); } int64_t as_integer() const { return const_value().asInt64(); } double as_number() const { return const_value().asDouble(); } std::string as_string() const { return const_value().asString(); } JsonCppObjectAdapter as_object() const { return value(); } static std::string key(auto it) { return it.key().asString(); } using detail::SimpleAdapter::assign; void assign(Adapter const & adapter) const requires(not std::is_const_v) { switch (adapter.type()) { case Type::Null: *value() = Json::nullValue; return; case Type::Boolean: *value() = adapter.as_boolean(); return; case Type::Integer: *value() = adapter.as_integer(); return; case Type::Number: *value() = adapter.as_number(); return; case Type::String: *value() = adapter.as_string(); return; case Type::Array: adapter.apply_array([this, index = 0](Adapter const & elem) mutable { JsonCppAdapter((*value())[index]).assign(elem); ++index; return Status::Accept; }); return; case Type::Object: adapter.apply_object([this](std::string const & key, Adapter const & elem) { JsonCppAdapter((*value())[key]).assign(elem); return Status::Accept; }); return; } } public : using JsonCppAdapter::SimpleAdapter::value; using JsonCppAdapter::SimpleAdapter::const_value; }; }