13#include <nlohmann/json.hpp>
32using object_t = nlohmann::basic_json<>::object_t;
38namespace fs = std::filesystem;
41using json_t = nlohmann::json;
45 std::convertible_to<std::decay_t<T>, std::string>
46 or std::constructible_from<std::string, std::decay_t<T>>;
50using KeyType = json_t::value_t;
73 std::variant<json_t, std::reference_wrapper<json_t>> m_json;
77 template<
typename T>
requires std::same_as<std::remove_cvref_t<T>, json_t>
78 explicit Db(T&& json)
noexcept;
79 template<
typename T>
requires std::same_as<std::remove_cvref_t<T>, json_t>
80 explicit Db(std::reference_wrapper<T>
const& json)
noexcept;
82 [[maybe_unused]] [[nodiscard]] std::vector<std::string>
keys()
const noexcept;
83 [[maybe_unused]] [[nodiscard]] std::vector<std::pair<std::string, Db>>
items()
const noexcept;
84 template<
typename V = Db>
89 template<
typename F, IsString Ks>
90 [[maybe_unused]] [[nodiscard]]
decltype(
auto)
apply(F&& f, Ks&& ks);
93 [[maybe_unused]] [[nodiscard]]
bool empty() const noexcept;
96 [[maybe_unused]] [[nodiscard]]
bool contains(T&& t) const noexcept;
97 [[maybe_unused]] [[nodiscard]] KeyType
type() const noexcept;
100 [[maybe_unused]] [[nodiscard]]
bool erase(T&& t);
101 [[maybe_unused]]
void clear();
103 json_t const&
data() const;
106 Db& operator=(T&& t);
107 [[maybe_unused]] [[nodiscard]]
Db operator()(std::
string const& t);
109 friend std::ostream& operator<<(std::ostream& os,
Db const& db);
118inline
Db::
Db() noexcept : m_json(json_t::
object())
133template<
typename T>
requires std::same_as<std::remove_cvref_t<T>, json_t>
134inline Db::Db(std::reference_wrapper<T>
const& json) noexcept : m_json(json)
148template<
typename T>
requires std::same_as<std::remove_cvref_t<T>, json_t>
149inline Db::Db(T&& json) noexcept : m_json(json)
165 if (std::holds_alternative<std::reference_wrapper<json_t>>(m_json))
167 return std::get<std::reference_wrapper<json_t>>(m_json).get();
170 return std::get<json_t>(m_json);
184 return const_cast<Db*
>(
this)->
data();
197inline std::vector<std::string>
Db::keys() const noexcept
199 json_t
const& json =
data();
200 return_if(not json.is_structured(), {},
"E::Invalid non-structured json access");
202 | std::views::transform([&](
auto&& e) {
return e.key(); })
203 | std::ranges::to<std::vector<std::string>>();
216inline std::vector<std::pair<std::string,Db>>
Db::items() const noexcept
218 json_t
const& json =
data();
219 return_if(not json.is_structured(), {},
"E::Invalid non-structured json access");
221 | std::views::transform([](
auto&& e){
return std::make_pair(e.key(),
Db{e.value()}); })
222 | std::ranges::to<std::vector<std::pair<std::string,Db>>>();
240 json_t& json =
data();
241 if constexpr ( std::same_as<V,Db> )
247 return_if(not json.is_array(), Error(
"D::Tried to create array with non-array entry"));
248 return_if(std::any_of(json.begin(), json.end(), [](
auto&& e){ return not e.is_string(); })
249 , Error(
"D::Invalid key type for string array")
251 return std::ranges::subrange(json.begin(), json.end())
252 | std::views::transform([](
auto&& e){
return typename std::remove_cvref_t<V>::value_type(e); })
253 | std::ranges::to<V>();
257 return ( json.is_string() )?
259 : Error(
"D::Json element is not a string");
263 static_assert(std::is_same_v<V, V> ==
false,
"Unsupported type V for value()");
264 return Error(
"D::No viable type conversion");
293 return data().empty();
311 json_t
const& json =
data();
312 return (json.is_object() || json.is_array()) && json.contains(key);
326 return data().type();
347 json_t& json =
data();
349 if ( json.is_array() )
351 auto it_search = std::find(json.begin(), json.end(), str_key);
352 if ( it_search == json.end() ) {
return false; }
353 json.erase(std::distance(json.begin(), it_search));
356 else if(json.is_object())
358 return json.erase(str_key) > 0;
372 data() = json_t::object();
406 json_t& json =
data();
408 if(json.is_object() or json.empty())
410 return Db{std::reference_wrapper<json_t>(json[key])};
446 return_if(not Try(fs::exists(path_file_db)), Error(
"D::Invalid db file '{}'", path_file_db.string()));
448 auto f_parse_file = [](std::ifstream
const& f) ->
Value<json_t>
453 return Try(json_t::parse(contents));
456 std::ifstream file(path_file_db, std::ios::in);
457 return_if(not file.is_open(), Error(
"D::Failed to open '{}'", path_file_db.string()));
459 return Db(Pop(f_parse_file(file)));
476 std::ofstream file(path_file_db, std::ios::trunc);
477 return_if(not file.is_open(), Error(
"D::Failed to open '{}' for writing", path_file_db.string()));
478 file << std::setw(2) << Pop(db.
dump());
495template<ns_concept::StringRepresentable S>
499 return_if(
data.empty(), Error(
"D::Empty json data"));
500 return Try(
Db{json_t::parse(
data)},
"D::Could not parse json file");
A type-safe wrapper around nlohmann::json for database operations.
bool contains(T &&t) const noexcept
Checks if the JSON contains a specific key.
Db() noexcept
Constructs a new Db object with an empty JSON object.
friend std::ostream & operator<<(std::ostream &os, Db const &db)
Outputs the JSON data to an output stream.
std::vector< std::string > keys() const noexcept
Retrieves all keys from the current JSON object or array.
KeyType type() const noexcept
Retrieves the type of the current JSON element.
Db operator()(std::string const &t)
Accesses or creates a nested JSON entry by key.
std::vector< std::pair< std::string, Db > > items() const noexcept
Retrieves key-value pairs as Db objects from the current JSON.
void clear()
Resets the JSON data to an empty object.
json_t & data()
Retrieves a mutable reference to the underlying JSON data.
bool erase(T &&t)
Removes a key from the JSON structure.
decltype(auto) apply(F &&f, Ks &&ks)
Value< V > value() noexcept
Converts the current JSON entry to a specified type.
Value< std::string > dump()
Serializes the current JSON data to a formatted string.
Db & operator=(T &&t)
Assigns a new value to the underlying JSON data.
bool empty() const noexcept
Checks whether the JSON data is empty.
Custom C++ concepts for type constraints and compile-time validation.
Concept for std::vector types.
Concept for types that can construct a std::string.
Enhanced error handling framework built on std::expected.
Simplified macros for common control flow patterns with optional logging.
JSON-based configuration database layer.
Value< Db > from_string(S &&s)
Parses a JSON string and creates a Db object.
Value< void > write_file(fs::path const &path_file_db, Db &db)
Serializes a Db object and writes it to a JSON file.
Value< Db > read_file(fs::path const &path_file_db)
Deserializes a JSON file into a Db object.
std::string to_string(T &&t) noexcept
Converts a type to a string.
Enhanced expected type with integrated logging capabilities.