diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7ee6d193f6814d1d24eb8cb35e3658a87d00e601..09d03a7a78fc5b9bd3b49f242a32d97debccfe3a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -323,7 +323,7 @@ if(_LINTING)
     else()
         message(STATUS "clang-tidy: ${clang_tidy}")
         set(_CMAKE_CXX_CLANG_TIDY_CHECKS
-            "--checks=*,-fuchsia-*,-llvmlibc-*,-readability-convert-member-functions-to-static,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-hicpp-no-array-decay,-llvm-else-after-return,-readability-else-after-return,-modernize-use-trailing-return-type,-bugprone-branch-clone,-altera-*")
+            "--checks=*,-fuchsia-*,-llvmlibc-*,-readability-convert-member-functions-to-static,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-hicpp-no-array-decay,-llvm-else-after-return,-readability-else-after-return,-modernize-use-trailing-return-type,-bugprone-branch-clone,-altera-*,-cppcoreguidelines-macro-usage,-*-avoid-c-arrays")
         set(_CMAKE_C_CLANG_TIDY_CHECKS "${_CMAKE_CXX_CLANG_TIDY_CHECKS}")
         set(_CMAKE_CXX_CLANG_TIDY "${clang_tidy}"
             "--header-filter=caosdb/.*[^\(\.pb\.h\)]$"
diff --git a/include/caosdb/configuration.h b/include/caosdb/configuration.h
index 092522d1bb3a30980036e7c6acb71ddb8b78be5c..053888672ab3e1649a060553264fe8d26fda9907 100644
--- a/include/caosdb/configuration.h
+++ b/include/caosdb/configuration.h
@@ -25,27 +25,20 @@
 #include "caosdb/authentication.h"         // for Authenticator, PlainPassw...
 #include "caosdb/certificate_provider.h"   // for CertificateProvider, path
 #include "caosdb/exceptions.h"             // for ConfigurationError
-#include "caosdb/logging.h"                // for SinkConfiguration, Loggin...
 #include "caosdb/utility.h"                // for load_json_file
 #include <google/protobuf/arena.h>         // for Arena
 #include <google/protobuf/extension_set.h> // for Arena
 #include <grpcpp/security/credentials.h>   // for ChannelCredentials
-#include <boost/json/object.hpp>           // for object
-#include <boost/json/value.hpp>            // for value
-#include <boost/json/value_ref.hpp>        // for array, object
-// IWYU pragma: no_include "boost/json/fwd.hpp"
-#include <filesystem> // for path, exists
-#include <iosfwd>     // for ostream
-#include <memory>     // for shared_ptr, unique_ptr
-#include <string>     // for string
+#include <filesystem>                      // for path, exists
+#include <iosfwd>                          // for ostream
+#include <memory>                          // for shared_ptr, unique_ptr
+#include <string>                          // for string
 
 namespace caosdb::configuration {
-using boost::json::array;
-using boost::json::object;
-using boost::json::value;
 using caosdb::authentication::Authenticator;
 using caosdb::authentication::PlainPasswordAuthenticator;
 using caosdb::exceptions::ConfigurationError;
+using caosdb::utility::JsonValue;
 using caosdb::utility::load_json_file;
 using google::protobuf::Arena;
 using grpc::ChannelCredentials;
@@ -102,69 +95,6 @@ public:
   [[nodiscard]] auto ToString() const -> std::string override;
 };
 
-/**
- * Helper class (no state, just member functions) which should only be used by
- * the ConfigurationManager to initialize the logging framework from the stored
- * configuration.
- */
-class LoggingConfigurationHelper {
-public:
-  friend class ConfigurationManager;
-
-private:
-  auto ConvertLogLevel(const std::string &string_level) const -> int;
-  auto CreateConsoleSinkConfiguration(const object &from, const std::string &name, int level) const
-    -> std::shared_ptr<caosdb::logging::SinkConfiguration>;
-  auto CreateSyslogSinkConfiguration(const object &from, const std::string &name, int level) const
-    -> std::shared_ptr<caosdb::logging::SinkConfiguration>;
-  auto CreateFileSinkConfiguration(const object &from, const std::string &name, int level) const
-    -> std::shared_ptr<caosdb::logging::SinkConfiguration>;
-  auto CreateSinkConfiguration(const object &from, const std::string &name, int default_level) const
-    -> std::shared_ptr<caosdb::logging::SinkConfiguration>;
-  auto CreateLoggingConfiguration(const object &from) const
-    -> caosdb::logging::LoggingConfiguration;
-};
-
-/**
- * Helper class (no state, just member functions) which should only be used by
- * the ConfigurationManager to construct Connection instances from the stored
- * configuration.
- */
-class ConnectionConfigurationHelper {
-public:
-  friend class ConfigurationManager;
-
-private:
-  /**
-   * @param from - a single connection configuration.
-   */
-  auto CreateCertificateProvider(const object &from) const -> std::unique_ptr<CertificateProvider>;
-
-  /**
-   * @param from - a single connection configuration.
-   */
-  auto CreateAuthenticator(const object &from) const -> std::unique_ptr<Authenticator>;
-
-  /**
-   * @param from - a single connection configuration.
-   */
-  auto CreateConnectionConfiguration(const bool tls, const std::string &host, const int port,
-                                     const CertificateProvider *certificate_provider,
-                                     const Authenticator *authenticator) const
-    -> std::unique_ptr<ConnectionConfiguration>;
-
-  /**
-   * @param from - a single connection configuration.
-   */
-  auto IsTls(const object &from) const -> bool;
-
-  /**
-   * @param from - a single connection configuration.
-   */
-  auto CreateConnectionConfiguration(const object &from) const
-    -> std::unique_ptr<ConnectionConfiguration>;
-};
-
 /**
  * Reads the configuration file and keeps the configuration. Singleton.
  *
@@ -225,13 +155,12 @@ public:
 
 private:
   Arena arena;
-  value json_configuration;
-  ConnectionConfigurationHelper connection_configuration_helper;
-  LoggingConfigurationHelper logging_configuration_helper;
+  JsonValue json_configuration;
 
-  inline ConfigurationManager(){
-    // InitializeDefaults();
-  };
+  inline ConfigurationManager()
+    : json_configuration(nullptr){
+        // InitializeDefaults();
+      };
 
   /**
    * Initialize this ConfigurationManager with the defaults.
@@ -242,22 +171,6 @@ private:
    */
   auto InitializeDefaults() -> int;
 
-  /**
-   * Return a json object representing the current configuration.
-   */
-  auto GetConfiguration() const -> const object &;
-
-  /**
-   * Return the connection configurations.
-   */
-  auto GetConnections() const -> const object &;
-
-  /**
-   * Return the configuration for the connection with the given name (as a json
-   * object).
-   */
-  auto GetConnection(const std::string &name) const -> const object &;
-
   /**
    * Reset this ConfigurationManager.
    *
diff --git a/include/caosdb/utility.h b/include/caosdb/utility.h
index 0a4d65e883ccfb6cc8f41d1c412bef5433b89417..a27ab64f068d008ace914676cee675851313eef5 100644
--- a/include/caosdb/utility.h
+++ b/include/caosdb/utility.h
@@ -21,27 +21,14 @@
 
 #ifndef CAOSDB_UTILS_H
 #define CAOSDB_UTILS_H
-#include "caosdb/data_type.h"                 // for AtomicDataType
-#include "caosdb/entity.h"                    // for Importance, Role
-#include <boost/beast/core/detail/base64.hpp> // for encoded_size
-#include <boost/beast/core/detail/base64.ipp> // for encode
-#include <boost/filesystem/string_file.hpp>   // for load_string_file
-#include <boost/json/stream_parser.hpp>       // for stream_parser
-#include <boost/json/value.hpp>               // for value
-#include <boost/lexical_cast.hpp>             // for lexical_cast
-#include <cassert>                            // for assert
-#include <cstdlib>                            // for getenv
-#include <filesystem>                         // for path
-#include <fstream>                            // for basic_istream<>::__ist...
-#include <memory>                             // for allocator, unique_ptr
-#include <stdexcept>                          // for logic_error
-#include <string>                             // for string, operator+, cha...
-#include <type_traits>                        // for underlying_type_t
-#include <typeinfo>                           // for type_info
+#include "caosdb/data_type.h" // for AtomicDataType
+#include "caosdb/entity.h"    // for Importance, Role
+#include <cstdlib>            // for getenv
+#include <filesystem>         // for path
+#include <fstream>            // for basic_istream<>::__ist...
+#include <string>             // for string, operator+, cha...
 
 namespace caosdb::utility {
-using boost::json::stream_parser;
-using boost::json::value;
 using std::ifstream;
 using std::filesystem::exists;
 using std::filesystem::path;
@@ -49,12 +36,7 @@ using std::filesystem::path;
 /**
  * @brief Get the name of the enum value.  May be useful for higher-order CaosDB clients.
  */
-template <typename Enum> auto getEnumNameFromValue(Enum v) -> std::string {
-  if (std::is_same_v<std::underlying_type_t<Enum>, int>) {
-    return boost::lexical_cast<std::string>(static_cast<int>(v));
-  }
-  throw std::logic_error(std::string("Enum type ") + typeid(v).name() + " not implemented.");
-}
+template <typename Enum> auto getEnumNameFromValue(Enum v) -> std::string;
 
 // Forward declaration of specializations
 template <>
@@ -84,11 +66,7 @@ auto getEnumValueFromName<caosdb::entity::Role>(const std::string &name) -> caos
 /**
  * @brief Read a text file into a string and return the file's content.
  */
-inline auto load_string_file(const path &file_path) -> std::string {
-  std::string result;
-  boost::filesystem::load_string_file(file_path.string(), result);
-  return result;
-}
+auto load_string_file(const path &file_path) -> std::string;
 
 /**
  * @brief Return the environment variable KEY, or FALLBACK if it does not exist.
@@ -115,37 +93,81 @@ inline auto get_env_fallback(const std::string &key, const std::string &fallback
 }
 
 /**
- * @brief Encode string as base64
+ * @brief JsonValue is a thin wrapper around a implementation specific
+ * third-party json object (e.g. boost).
  */
-inline auto base64_encode(const std::string &plain) -> std::string {
-  auto size_plain = plain.size();
-  auto size_encoded = boost::beast::detail::base64::encoded_size(size_plain);
-
-  std::unique_ptr<char[]> encoded(new char[size_encoded]);
-  boost::beast::detail::base64::encode(encoded.get(), plain.c_str(), size_plain);
-
-  // the encoded char[] is not null terminated, so explicitely set the length
-  return std::string(encoded.get(), encoded.get() + size_encoded);
-}
-
-inline auto load_json_file(const path &json_file) -> value {
-  assert(exists(json_file));
+class JsonValue {
+public:
+  /**
+   * Constructor.
+   *
+   * By calling this constructor the ownership of the `wrapped` parameter is
+   * transferred to this object.
+   */
+  JsonValue(void *wrapped) : wrapped(wrapped) {}
+  /**
+   * Destructor.
+   *
+   * Also deletes the `wrapped` object.
+   */
+  ~JsonValue();
+
+  /**
+   * Copy Constructor.
+   *
+   * Also copies the `wrapped` object.
+   */
+  JsonValue(const JsonValue &other);
+
+  /**
+   * Copy Assigment.
+   *
+   * Also copies the `wrapped` object.
+   */
+  auto operator=(const JsonValue &other) -> JsonValue & = default;
+
+  /**
+   * Move Constructor.
+   *
+   * Also moves the `wrapped` object.
+   */
+  JsonValue(JsonValue &&other);
+
+  /**
+   * Move Assigment.
+   *
+   * Also moves the `wrapped` object.
+   */
+  auto operator=(JsonValue &&other) -> JsonValue & = default;
+
+  /**
+   * Return true if the `wrapped` object is the nullptr.
+   */
+  inline auto IsNull() const -> bool { return this->wrapped == nullptr; }
+
+  /**
+   * Reset this object.
+   *
+   * Also deletes `wrapped` sets it to the nullptr.
+   */
+  auto Reset() -> void;
+
+  /**
+   * An object which represents a JSON value. The object's class is an
+   * implementation detail.
+   */
+  void *wrapped;
+};
 
-  constexpr auto buffer_size = std::size_t(4096);
-  auto stream = ifstream(json_file);
-  stream.exceptions(std::ios_base::badbit);
-
-  stream_parser parser;
-  auto result = std::string();
-  auto buffer = std::string(buffer_size, '\0');
-  while (stream.read(&buffer[0], buffer_size)) {
-    parser.write(buffer.c_str(), stream.gcount());
-  }
-  parser.write(buffer.c_str(), stream.gcount());
+/**
+ * @brief Load json object from a json file and return it.
+ */
+auto load_json_file(const path &json_file) -> JsonValue;
 
-  assert(parser.done());
-  return parser.release();
-}
+/**
+ * @brief Encode string as base64
+ */
+auto base64_encode(const std::string &plain) -> std::string;
 
 inline auto get_home_directory() -> const path {
   const auto *const home = getenv("HOME");
diff --git a/src/caosdb/configuration.cpp b/src/caosdb/configuration.cpp
index 41d19616acdd450aa5e8057dd1966000f46e0803..d8a3050d82323689e7ee2ffb76084669257042ff 100644
--- a/src/caosdb/configuration.cpp
+++ b/src/caosdb/configuration.cpp
@@ -24,6 +24,7 @@
 #include "caosdb/constants.h"         // for LIBCAOSDB_CONF...
 #include "caosdb/exceptions.h"        // for ConfigurationE...
 #include "caosdb/log_level.h"         // for CAOSDB_DEFAULT...
+#include "caosdb/logging.h"           // for SinkConfiguration, Loggin...
 #include "caosdb/status_code.h"       // for StatusCode
 #include "caosdb/utility.h"           // for get_home_direc...
 #include <boost/json/impl/object.hpp> // for object::at
@@ -44,6 +45,27 @@
 #include <string>                        // for string, operator+
 #include <utility>                       // for move
 
+#define WRAPPED_JSON_CONFIGURATION(obj) (static_cast<value *>((obj)->json_configuration.wrapped))
+
+#define GET_CONNECTIONS                                                                            \
+  if (this->json_configuration.IsNull()) {                                                         \
+    throw ConfigurationError("This CaosDB client has not been configured.");                       \
+  }                                                                                                \
+  assert(WRAPPED_JSON_CONFIGURATION(this)->is_object());                                           \
+  const auto &configuration = WRAPPED_JSON_CONFIGURATION(this)->as_object();                       \
+  if (!configuration.contains("connections")) {                                                    \
+    throw ConfigurationError("This CaosDB client hasn't any configured connections.");             \
+  }                                                                                                \
+  const auto &connections_value = configuration.at("connections");                                 \
+  if (connections_value.is_null()) {                                                               \
+    throw ConfigurationError("This CaosDB client hasn't any configured connections.");             \
+  }                                                                                                \
+  assert(connections_value.is_object());                                                           \
+  const auto &connections = connections_value.as_object();                                         \
+  if (connections.empty()) {                                                                       \
+    throw ConfigurationError("This CaosDB client hasn't any configured connections.");             \
+  }
+
 namespace caosdb::configuration {
 using boost::json::object;
 using boost::json::value;
@@ -151,8 +173,7 @@ auto TlsConnectionConfiguration::ToString() const -> std::string {
          "," + this->certificate_provider + ")";
 }
 
-auto ConnectionConfigurationHelper::CreateCertificateProvider(const object &from) const
-  -> std::unique_ptr<CertificateProvider> {
+auto CreateCertificateProvider(const object &from) -> std::unique_ptr<CertificateProvider> {
   std::unique_ptr<CertificateProvider> certificate_provider;
   if (from.contains("server_certificate_path")) {
     const value &path_str = from.at("server_certificate_path");
@@ -168,8 +189,7 @@ auto ConnectionConfigurationHelper::CreateCertificateProvider(const object &from
   return certificate_provider;
 }
 
-auto ConnectionConfigurationHelper::CreateAuthenticator(const object &from) const
-  -> std::unique_ptr<Authenticator> {
+auto CreateAuthenticator(const object &from) -> std::unique_ptr<Authenticator> {
   std::unique_ptr<Authenticator> authenticator;
   if (from.contains("authentication")) {
     assert(from.at("authentication").is_object());
@@ -197,9 +217,9 @@ auto ConnectionConfigurationHelper::CreateAuthenticator(const object &from) cons
   return authenticator;
 }
 
-auto ConnectionConfigurationHelper::CreateConnectionConfiguration(
-  const bool tls, const std::string &host, const int port,
-  const CertificateProvider *certificate_provider, const Authenticator *authenticator) const
+auto CreateConnectionConfiguration(const bool tls, const std::string &host, const int port,
+                                   const CertificateProvider *certificate_provider,
+                                   const Authenticator *authenticator)
   -> std::unique_ptr<ConnectionConfiguration> {
   if (tls) {
     if (certificate_provider != nullptr && authenticator != nullptr) {
@@ -220,7 +240,7 @@ auto ConnectionConfigurationHelper::CreateConnectionConfiguration(
   }
 }
 
-auto ConnectionConfigurationHelper::IsTls(const object &from) const -> bool {
+auto IsTls(const object &from) -> bool {
   bool tls = true;
   if (from.contains("tls")) {
     auto tls_switch = from.at("tls");
@@ -230,8 +250,7 @@ auto ConnectionConfigurationHelper::IsTls(const object &from) const -> bool {
   return tls;
 }
 
-auto ConnectionConfigurationHelper::CreateConnectionConfiguration(const object &from) const
-  -> std::unique_ptr<ConnectionConfiguration> {
+auto CreateConnectionConfiguration(const object &from) -> std::unique_ptr<ConnectionConfiguration> {
   assert(from.contains("host"));
   const auto &host = from.at("host");
   assert(host.is_string());
@@ -251,25 +270,19 @@ auto ConnectionConfigurationHelper::CreateConnectionConfiguration(const object &
                                        certificate_provider.get(), authenticator.get());
 }
 
-auto LoggingConfigurationHelper::CreateConsoleSinkConfiguration(const object & /*from*/,
-                                                                const std::string &name,
-                                                                int level) const
+auto CreateConsoleSinkConfiguration(const object & /*from*/, const std::string &name, int level)
   -> std::shared_ptr<caosdb::logging::SinkConfiguration> {
   auto result = std::make_shared<ConsoleSinkConfiguration>(name, level);
   return result;
 }
 
-auto LoggingConfigurationHelper::CreateSyslogSinkConfiguration(const object & /*from*/,
-                                                               const std::string &name,
-                                                               int level) const
+auto CreateSyslogSinkConfiguration(const object & /*from*/, const std::string &name, int level)
   -> std::shared_ptr<caosdb::logging::SinkConfiguration> {
   auto result = std::make_shared<SyslogSinkConfiguration>(name, level);
   return result;
 }
 
-auto LoggingConfigurationHelper::CreateFileSinkConfiguration(const object &from,
-                                                             const std::string &name,
-                                                             int level) const
+auto CreateFileSinkConfiguration(const object &from, const std::string &name, int level)
   -> std::shared_ptr<caosdb::logging::SinkConfiguration> {
   auto result = std::make_shared<FileSinkConfiguration>(name, level);
   if (from.contains("directory")) {
@@ -278,9 +291,21 @@ auto LoggingConfigurationHelper::CreateFileSinkConfiguration(const object &from,
   return result;
 }
 
-auto LoggingConfigurationHelper::CreateSinkConfiguration(const object &from,
-                                                         const std::string &name,
-                                                         int default_level) const
+auto ConvertLogLevel(const std::string &string_level) -> int {
+  static std::map<std::string, int> log_level_names = {
+    {"", CAOSDB_DEFAULT_LOG_LEVEL},    {"off", CAOSDB_LOG_LEVEL_OFF},
+    {"fatal", CAOSDB_LOG_LEVEL_FATAL}, {"error", CAOSDB_LOG_LEVEL_ERROR},
+    {"warn", CAOSDB_LOG_LEVEL_WARN},   {"info", CAOSDB_LOG_LEVEL_INFO},
+    {"debug", CAOSDB_LOG_LEVEL_DEBUG}, {"trace", CAOSDB_LOG_LEVEL_TRACE},
+    {"all", CAOSDB_LOG_LEVEL_ALL}};
+  try {
+    return log_level_names.at(string_level);
+  } catch (const std::out_of_range &exc) {
+    throw ConfigurationError("Unknown log level: " + string_level);
+  }
+}
+
+auto CreateSinkConfiguration(const object &from, const std::string &name, int default_level)
   -> std::shared_ptr<caosdb::logging::SinkConfiguration> {
   assert(from.contains("destination"));
   const auto &destination = std::string(from.at("destination").as_string().c_str());
@@ -299,22 +324,7 @@ auto LoggingConfigurationHelper::CreateSinkConfiguration(const object &from,
   }
 }
 
-auto LoggingConfigurationHelper::ConvertLogLevel(const std::string &string_level) const -> int {
-  static std::map<std::string, int> log_level_names = {
-    {"", CAOSDB_DEFAULT_LOG_LEVEL},    {"off", CAOSDB_LOG_LEVEL_OFF},
-    {"fatal", CAOSDB_LOG_LEVEL_FATAL}, {"error", CAOSDB_LOG_LEVEL_ERROR},
-    {"warn", CAOSDB_LOG_LEVEL_WARN},   {"info", CAOSDB_LOG_LEVEL_INFO},
-    {"debug", CAOSDB_LOG_LEVEL_DEBUG}, {"trace", CAOSDB_LOG_LEVEL_TRACE},
-    {"all", CAOSDB_LOG_LEVEL_ALL}};
-  try {
-    return log_level_names.at(string_level);
-  } catch (const std::out_of_range &exc) {
-    throw ConfigurationError("Unknown log level: " + string_level);
-  }
-}
-
-auto LoggingConfigurationHelper::CreateLoggingConfiguration(const object &from) const
-  -> LoggingConfiguration {
+auto CreateLoggingConfiguration(const object &from) -> LoggingConfiguration {
   auto default_level_str =
     from.contains("level") ? std::string(from.at("level").as_string().c_str()) : "";
   int default_level = ConvertLogLevel(default_level_str);
@@ -356,7 +366,7 @@ auto ConfigurationManager::mReset() noexcept -> int {
 
 auto ConfigurationManager::mClear() noexcept -> int {
   try {
-    json_configuration = value(nullptr);
+    json_configuration.Reset();
     ConnectionManager::Reset();
     return StatusCode::SUCCESS;
   } catch (const caosdb::exceptions::Exception &exc) {
@@ -369,7 +379,7 @@ auto ConfigurationManager::mClear() noexcept -> int {
 }
 
 auto ConfigurationManager::mLoadSingleJSONConfiguration(const path &json_file) -> void {
-  if (!json_configuration.is_null()) {
+  if (!json_configuration.IsNull()) {
     throw ConfigurationError("This CaosDB client has already been configured.");
   }
   if (!exists(json_file)) {
@@ -381,12 +391,17 @@ auto ConfigurationManager::mLoadSingleJSONConfiguration(const path &json_file) -
 
 auto ConfigurationManager::mGetConnectionConfiguration(const std::string &name) const
   -> std::unique_ptr<ConnectionConfiguration> {
-  auto connection_json = GetConnection(name);
-  return connection_configuration_helper.CreateConnectionConfiguration(connection_json);
+  GET_CONNECTIONS
+  if (connections.contains(name)) {
+    const auto &result_connection = connections.at(name);
+    assert(result_connection.is_object());
+    return CreateConnectionConfiguration(result_connection.as_object());
+  }
+  throw ConfigurationError("The connection '" + name + "' has not been defined.");
 }
 
 auto ConfigurationManager::mGetDefaultConnectionName() const -> std::string {
-  auto connections = GetConnections();
+  GET_CONNECTIONS
   if (connections.contains("default")) {
     auto default_connection = connections.at("default");
     if (default_connection.is_object()) {
@@ -406,41 +421,6 @@ auto ConfigurationManager::mGetDefaultConnectionName() const -> std::string {
   throw ConfigurationError("Could not determine the default connection.");
 }
 
-auto ConfigurationManager::GetConfiguration() const -> const object & {
-  if (json_configuration.is_null()) {
-    throw ConfigurationError("This CaosDB client has not been configured.");
-  }
-  assert(json_configuration.is_object());
-  return json_configuration.as_object();
-}
-
-auto ConfigurationManager::GetConnections() const -> const object & {
-  const auto &configuration = GetConfiguration();
-  if (!configuration.contains("connections")) {
-    throw ConfigurationError("This CaosDB client hasn't any configured connections.");
-  }
-  const auto &connections_value = configuration.at("connections");
-  if (connections_value.is_null()) {
-    throw ConfigurationError("This CaosDB client hasn't any configured connections.");
-  }
-  assert(connections_value.is_object());
-  const auto &connections_object = connections_value.as_object();
-  if (connections_object.empty()) {
-    throw ConfigurationError("This CaosDB client hasn't any configured connections.");
-  }
-  return connections_object;
-}
-
-auto ConfigurationManager::GetConnection(const std::string &name) const -> const object & {
-  const auto &connections = GetConnections();
-  if (connections.contains(name)) {
-    const auto &result_connection = connections.at(name);
-    assert(result_connection.is_object());
-    return result_connection.as_object();
-  }
-  throw ConfigurationError("The connection '" + name + "' has not been defined.");
-}
-
 // TODO(tf) This has apparently a cognitive complexity of 34>25 (threshold).
 auto ConfigurationManager::InitializeDefaults() -> int { // NOLINT
 
@@ -488,11 +468,10 @@ auto ConfigurationManager::InitializeDefaults() -> int { // NOLINT
   }
 
   // Logging in the configuration leads to additional content.
-  if (this->json_configuration.is_object() &&
-      this->json_configuration.as_object().contains("logging")) {
+  if (WRAPPED_JSON_CONFIGURATION(this)->is_object() &&
+      WRAPPED_JSON_CONFIGURATION(this)->as_object().contains("logging")) {
     LoggingConfiguration logging_configuration =
-      logging_configuration_helper.CreateLoggingConfiguration(
-        json_configuration.at("logging").as_object());
+      CreateLoggingConfiguration(WRAPPED_JSON_CONFIGURATION(this)->at("logging").as_object());
     logging::initialize_logging(logging_configuration);
   } else {
     logging::initialize_logging_defaults();
@@ -500,7 +479,7 @@ auto ConfigurationManager::InitializeDefaults() -> int { // NOLINT
                                     "We are using the default configuration";
   }
 
-  if (configuration_file_path != nullptr && this->json_configuration.is_object()) {
+  if (configuration_file_path != nullptr && WRAPPED_JSON_CONFIGURATION(this)->is_object()) {
     CAOSDB_LOG_INFO(logger_name) << "Loaded configuration from " << *(configuration_file_path)
                                  << ".";
   }
diff --git a/src/caosdb/utility.cpp b/src/caosdb/utility.cpp
index a4ed293adb6bd4fbfb10860e03185aeb567de163..6a9c8ec0bae052649e0c72ecc4b15bd08f163b95 100644
--- a/src/caosdb/utility.cpp
+++ b/src/caosdb/utility.cpp
@@ -19,18 +19,35 @@
  *
  */
 #include "caosdb/utility.h"
-#include "caosdb/data_type.h" // for AtomicDataType, atomicdatatype_names
-#include "caosdb/entity.h"    // for Importance, Role, importance_names
-#include <map>                // for map, operator!=, _Rb_tree_const_iterator
-#include <utility>            // for pair
+#include "caosdb/data_type.h"                 // for AtomicDataType, atomicdatatype_names
+#include "caosdb/entity.h"                    // for Importance, Role, importance_names
+#include <boost/beast/core/detail/base64.hpp> // for encoded_size
+#include <boost/beast/core/detail/base64.ipp> // for encode
+#include <boost/filesystem/string_file.hpp>   // for load_string_file
+#include <boost/json/stream_parser.hpp>       // for stream_parser
+#include <boost/json/value.hpp>               // for value
+#include <cassert>                            // for assert
+#include <map>                                // for map, operator!=, _Rb_tree_const_iterator
+#include <memory>                             // for allocator, unique_ptr
+#include <stdexcept>                          // for logic_error
+#include <type_traits>                        // for underlying_type_t
+#include <typeinfo>                           // for type_info
+#include <utility>                            // for pair
 
 namespace caosdb::utility {
 
+using boost::json::stream_parser;
+using boost::json::value;
 using caosdb::entity::AtomicDataType;
 using caosdb::entity::Importance;
 using caosdb::entity::Role;
 
-// using emap = std::map<int, std::string>;          // enum mapping
+template <typename Enum> auto getEnumNameFromValue(Enum v) -> std::string {
+  if (std::is_same_v<std::underlying_type_t<Enum>, int>) {
+    return std::to_string(static_cast<int>(v));
+  }
+  throw std::logic_error(std::string("Enum type ") + typeid(v).name() + " not implemented.");
+}
 
 // Enum helper template specializations //////////////////////////////////////
 template <> auto getEnumNameFromValue<Importance>(Importance v) -> std::string {
@@ -87,4 +104,53 @@ template <> auto getEnumValueFromName<Role>(const std::string &name) -> Role {
 
 // End of template specialization /////////////////////////////////////////////
 
+auto load_string_file(const path &file_path) -> std::string {
+  std::string result;
+  boost::filesystem::load_string_file(file_path.string(), result);
+  return result;
+}
+
+auto base64_encode(const std::string &plain) -> std::string {
+  auto size_plain = plain.size();
+  auto size_encoded = boost::beast::detail::base64::encoded_size(size_plain);
+
+  std::unique_ptr<char[]> encoded(new char[size_encoded]);
+  boost::beast::detail::base64::encode(encoded.get(), plain.c_str(), size_plain);
+
+  // the encoded char[] is not null terminated, so explicitely set the length
+  return {encoded.get(), encoded.get() + size_encoded};
+}
+
+auto _load_json_file(const path &json_file) -> value {
+  assert(exists(json_file));
+
+  constexpr auto buffer_size = std::size_t(4096);
+  auto stream = ifstream(json_file);
+  stream.exceptions(std::ios_base::badbit);
+
+  stream_parser parser;
+  auto result = std::string();
+  auto buffer = std::string(buffer_size, '\0');
+  while (stream.read(&buffer[0], buffer_size)) {
+    parser.write(buffer.c_str(), stream.gcount());
+  }
+  parser.write(buffer.c_str(), stream.gcount());
+
+  assert(parser.done());
+  return parser.release();
+}
+
+auto load_json_file(const path &json_file) -> JsonValue {
+  return {new value(_load_json_file(json_file))};
+}
+
+JsonValue::~JsonValue() { this->Reset(); }
+
+auto JsonValue::Reset() -> void {
+  if (!IsNull()) {
+    delete static_cast<value *>(this->wrapped);
+  }
+  this->wrapped = nullptr;
+}
+
 } // namespace caosdb::utility