diff --git a/include/caosdb/data_type.h b/include/caosdb/data_type.h
index 7afc694b6a3a723d126c21a45c52d9f4c9a7f710..ad5d35a92a1c1b468bfbfcca65e9b549c4f204de 100644
--- a/include/caosdb/data_type.h
+++ b/include/caosdb/data_type.h
@@ -46,9 +46,9 @@ class Entity;
 class Property;
 
 // Atomic data types.
-enum AtomicDataType {
+enum class AtomicDataType {
   // The data type is unset/unknown.
-  UNSPECIFIED_DATA_TYPE = ProtoAtomicDataType::ATOMIC_DATA_TYPE_UNSPECIFIED,
+  UNSPECIFIED = ProtoAtomicDataType::ATOMIC_DATA_TYPE_UNSPECIFIED,
   // TEXT data type.
   TEXT = ProtoAtomicDataType::ATOMIC_DATA_TYPE_TEXT,
   // DOUBLE data type.
@@ -61,6 +61,17 @@ enum AtomicDataType {
   BOOLEAN = ProtoAtomicDataType::ATOMIC_DATA_TYPE_BOOLEAN,
 };
 
+const std::map<AtomicDataType, std::string> atomicdatatype_names =
+  {
+   {AtomicDataType::UNSPECIFIED, "UNSPECIFIED"},
+   {AtomicDataType::TEXT, "TEXT"},
+   {AtomicDataType::DOUBLE, "DOUBLE"},
+   {AtomicDataType::DATETIME, "DATETIME"},
+   {AtomicDataType::INTEGER, "INTEGER"},
+   {AtomicDataType::BOOLEAN, "BOOLEAN"}
+  };
+
+
 class DataType;
 class ListDataType;
 
diff --git a/include/caosdb/entity.h b/include/caosdb/entity.h
index b66a0d21e0cacb89df8652a0bdee45a11f2adbc2..0734a3c1a9257e57f04a9e3829bf43d1992f8801 100644
--- a/include/caosdb/entity.h
+++ b/include/caosdb/entity.h
@@ -73,27 +73,43 @@ static const std::string logger_name = "caosdb::entity";
 /**
  * The property importance.
  */
-enum Importance {
-  IMPORTANCE_UNSPECIFIED =
-    ProtoImportance::IMPORTANCE_UNSPECIFIED, ///< Unset/None
+enum class Importance {
+  UNSPECIFIED =
+    ProtoImportance::IMPORTANCE_UNSPECIFIED,    ///< Unset/None
   OBLIGATORY =
-    ProtoImportance::IMPORTANCE_OBLIGATORY, ///< Obligatory importance.
+    ProtoImportance::IMPORTANCE_OBLIGATORY,     ///< Obligatory importance.
   RECOMMENDED =
-    ProtoImportance::IMPORTANCE_RECOMMENDED, ///< Recommended importance.
+    ProtoImportance::IMPORTANCE_RECOMMENDED,    ///< Recommended importance.
   SUGGESTED = ProtoImportance::IMPORTANCE_SUGGESTED, ///< Suggested importance.
   FIX = ProtoImportance::IMPORTANCE_FIX,             ///< Fix importance.
 };
+const std::map<Importance, std::string> importance_names =
+  {
+   {Importance::UNSPECIFIED, "UNSPECIFIED"},
+   {Importance::OBLIGATORY, "OBLIGATORY"},
+   {Importance::RECOMMENDED, "RECOMMENDED"},
+   {Importance::SUGGESTED, "SUGGESTED"},
+   {Importance::FIX, "FIX"}
+  };
 
 /**
  * The entity role.
  */
-enum Role {
-  ROLE_UNSPECIFIED = EntityRole::ENTITY_ROLE_UNSPECIFIED, ///< Unset/None
+enum class Role {
+  UNSPECIFIED = EntityRole::ENTITY_ROLE_UNSPECIFIED,      ///< Unset/None
   RECORD_TYPE = EntityRole::ENTITY_ROLE_RECORD_TYPE,      ///< RecordType
   RECORD = EntityRole::ENTITY_ROLE_RECORD,                ///< Record
   PROPERTY = EntityRole::ENTITY_ROLE_PROPERTY,            ///< Property
   FILE = EntityRole::ENTITY_ROLE_FILE,                    ///< File
 };
+const std::map<Role, std::string> role_names =
+  {
+   {Role::UNSPECIFIED, "UNSPECIFIED"},
+   {Role::RECORD_TYPE, "RECORD_TYPE"},
+   {Role::RECORD, "RECORD"},
+   {Role::PROPERTY, "PROPERTY"},
+   {Role::FILE, "FILE"}
+  };
 
 struct FileDescriptor {
   FileTransmissionId *file_transmission_id;
diff --git a/include/caosdb/utility.h b/include/caosdb/utility.h
index dd53ff952b9737fe76222d998b6813e744b0ad3d..0bc4ff12ded5ccb30f27f89444a47ed1f23055e2 100644
--- a/include/caosdb/utility.h
+++ b/include/caosdb/utility.h
@@ -21,20 +21,25 @@
 
 #ifndef CAOSDB_UTILS_H
 #define CAOSDB_UTILS_H
+#include "caosdb/entity.h"
+#include "caosdb/data_type.h"
 #include <boost/beast/core/detail/base64.hpp>
 #include <boost/filesystem.hpp>
 #include <boost/filesystem/fstream.hpp>
 #include <boost/filesystem/string_file.hpp>
+#include <boost/lexical_cast.hpp>                      // for lexical_cast
 #include <boost/json.hpp>
 #include <cassert>
 #include <cstdlib>
+#include <exception>                                   // for logic_error
 #include <fstream>
 #include <iostream>
+#include <map>
 #include <memory>
-#include <string>
-#include <string_view>
 #include <mutex>
 #include <shared_mutex>
+#include <string>
+#include <string_view>
 
 namespace caosdb::utility {
 using boost::filesystem::exists;
@@ -43,6 +48,49 @@ using boost::filesystem::path;
 using boost::json::stream_parser;
 using boost::json::value;
 
+/**
+ * @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.");
+}
+
+// Forward declaration of specializations
+template <>
+auto getEnumNameFromValue<caosdb::entity::AtomicDataType>(caosdb::entity::AtomicDataType v)
+  -> std::string;
+template <>
+auto getEnumNameFromValue<caosdb::entity::Importance>(caosdb::entity::Importance v)
+  -> std::string;
+template <>
+auto getEnumNameFromValue<caosdb::entity::Role>(caosdb::entity::Role v)
+  -> std::string;
+
+/**
+ * @brief Get the enum value from a string.
+ *
+ * @detail May be useful for higher-order CaosDB clients and only makes sense if specialized.
+ */
+template <typename Enum>
+auto getEnumValueFromName(const std::string &name) -> Enum {
+  throw std::logic_error(std::string("Enum type ") + typeid(Enum).name() + " not implemented.");
+}
+
+// Forward declaration of specializations
+template <>
+auto getEnumValueFromName<caosdb::entity::AtomicDataType>(const std::string &name)
+  -> caosdb::entity::AtomicDataType;
+template <>
+auto getEnumValueFromName<caosdb::entity::Importance>(const std::string &name)
+  -> caosdb::entity::Importance;
+template <>
+auto getEnumValueFromName<caosdb::entity::Role>(const std::string &name)
+  -> caosdb::entity::Role;
+
 /**
  * @brief Read a text file into a string and return the file's content.
  */
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 89180ee81fc6b07d4f081c90fd1200530a2d60b6..cb00898b70776b99c197556c435398d254578cbf 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -29,6 +29,7 @@ set(libcaosdb_SRC
     ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/protobuf_helper.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/transaction.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/transaction_handler.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/utility.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/unary_rpc_handler.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/file_transmission/register_file_upload_handler.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/caosdb/file_transmission/upload_request_handler.cpp
diff --git a/src/caosdb/utility.cpp b/src/caosdb/utility.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..243e85e31ac033c0ab0d60fef5ff81a496c8d44d
--- /dev/null
+++ b/src/caosdb/utility.cpp
@@ -0,0 +1,95 @@
+/*
+ * This file is a part of the CaosDB Project.
+ *
+ * Copyright (C) 2021 Daniel Hornung <d.hornung@indiscale.com>
+ * Copyright (C) 2021 IndiScale GmbH <info@indiscale.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+#include "caosdb/data_type.h"
+#include "caosdb/entity.h"
+#include "caosdb/utility.h"
+#include <algorithm>
+
+namespace caosdb::utility {
+
+using caosdb::entity::AtomicDataType;
+using caosdb::entity::Importance;
+using caosdb::entity::Role;
+
+
+// using emap = std::map<int, std::string>;          // enum mapping
+
+// Enum helper template specializations //////////////////////////////////////
+template <>
+auto getEnumNameFromValue<Importance>(Importance v) -> std::string {
+  auto result = caosdb::entity::importance_names.at(v);
+  return result;
+}
+
+template <>
+auto getEnumNameFromValue<Role>(Role v) -> std::string {
+  auto result = caosdb::entity::role_names.at(v);
+  return result;
+}
+
+template <>
+auto getEnumNameFromValue<AtomicDataType>(AtomicDataType v) -> std::string {
+  auto result = caosdb::entity::atomicdatatype_names.at(v);
+  return result;
+}
+
+template <>
+auto getEnumValueFromName<Importance>(const std::string &name) -> Importance {
+  // TODO (dh): Why does this compile?
+  // if (caosdb::entity::importance_names.begin()->second == name) {}
+  // std::for_each(caosdb::entity::importance_names.begin(),
+  //               caosdb::entity::importance_names.end(),
+  //               [](const auto &entry){});
+  // TODO (dh): Whereas this does not?
+  // auto result = std::find(caosdb::entity::importance_names.cbegin(),
+  //                         caosdb::entity::importance_names.cend(),
+  //                         [name](const auto& entry){ return entry.second == name; });
+  // Workaround: plaint old iteration:
+  for (auto entry: caosdb::entity::importance_names) {
+    if (entry.second == name) {
+      return entry.first;
+    }
+  }
+  throw std::out_of_range(std::string("Could not find enum value for string '") + name + "'.");
+}
+
+template <>
+auto getEnumValueFromName<AtomicDataType>(const std::string &name) -> AtomicDataType {
+  for (auto entry: caosdb::entity::atomicdatatype_names) {
+    if (entry.second == name) {
+      return entry.first;
+    }
+  }
+  throw std::out_of_range(std::string("Could not find enum value for string '") + name + "'.");
+}
+template <>
+auto getEnumValueFromName<Role>(const std::string &name) -> Role {
+  for (auto entry: caosdb::entity::role_names) {
+    if (entry.second == name) {
+      return entry.first;
+    }
+  }
+  throw std::out_of_range(std::string("Could not find enum value for string '") + name + "'.");
+}
+
+// End of template specialization /////////////////////////////////////////////
+
+} // namespace caosdb::utility
diff --git a/test/test_utility.cpp b/test/test_utility.cpp
index cb6021dc631c90b49ab8c3538f2b09fcc47723a3..3d302634f2729964f8763dcf3cfd17d5133460a1 100644
--- a/test/test_utility.cpp
+++ b/test/test_utility.cpp
@@ -24,6 +24,8 @@
 #include "boost/beast/core/detail/base64.hpp" // for encoded_size
 #include "boost/json/object.hpp"              // for object
 #include "boost/json/value.hpp"               // for value
+#include "caosdb/entity.h"                    // for importance_names, role...
+#include "caosdb/data_type.h"                 // for atomicdatatype_names
 #include "caosdb/utility.h"                   // for base64_encode, load_js...
 #include "caosdb_test_utility.h"              // for TEST_DATA_DIR
 #include <gtest/gtest-message.h>              // for Message
@@ -53,4 +55,29 @@ TEST(test_utility, test_load_json_file) {
   EXPECT_THAT(sub["see?"].as_array(), ElementsAre(true, false));
 }
 
+TEST(test_utility, enum_names) {
+  // All working enums
+  for (auto entry : caosdb::entity::importance_names) {
+    EXPECT_EQ(getEnumNameFromValue<caosdb::entity::Importance>(entry.first), entry.second);
+    EXPECT_EQ(getEnumValueFromName<caosdb::entity::Importance>(entry.second), entry.first);
+  }
+  for (auto entry : caosdb::entity::role_names) {
+    EXPECT_EQ(getEnumNameFromValue<caosdb::entity::Role>(entry.first), entry.second);
+    EXPECT_EQ(getEnumValueFromName<caosdb::entity::Role>(entry.second), entry.first);
+  }
+  for (auto entry : caosdb::entity::atomicdatatype_names) {
+    EXPECT_EQ(getEnumNameFromValue<caosdb::entity::AtomicDataType>(entry.first), entry.second);
+    EXPECT_EQ(getEnumValueFromName<caosdb::entity::AtomicDataType>(entry.second), entry.first);
+  }
+
+  // Some non-working examples
+  EXPECT_THROW_MESSAGE(getEnumValueFromName<caosdb::entity::Importance>("Invalid name"),
+                       std::out_of_range,
+                       "Could not find enum value for string 'Invalid name'.");
+  enum e1 {a};
+  EXPECT_THROW_STARTS_WITH(getEnumNameFromValue<e1>(a), std::logic_error, "Enum type ");
+  EXPECT_THROW_STARTS_WITH(getEnumValueFromName<e1>("Hello!"), std::logic_error, "Enum type ");
+}
+
+
 } // namespace caosdb::utility