diff --git a/src/config.cc b/src/config.cc
index ac7f6c95ba9581e6d301a551f3342790f0ab5cfd..072dfb201c13bfef0ab3a4d98cbfab37ad759290 100644
--- a/src/config.cc
+++ b/src/config.cc
@@ -1,6 +1,5 @@
 #include "config.h"
 
-#include <boost/algorithm/string.hpp>
 #include <cctype>
 #include <fstream>
 #include <functional>
@@ -53,31 +52,6 @@ ConfigMap::ConfigMap(std::string_view filename) {
   }
 }
 
-template <>
-std::vector<std::string> ConfigMap::Get<std::vector<std::string>>(const std::string &k) {
-  ValueType array = at(k);
-
-  std::vector<std::string> output;
-  for (int i = 0; i < static_cast<int>(array.size()); ++i) {
-    output.emplace_back(array[i].asString());
-  }
-  return output;
-}
-
-template <>
-std::vector<StreamConfig> ConfigMap::Get<std::vector<StreamConfig>>(const std::string &k) {
-  ValueType array = at(k);
-
-  std::vector<StreamConfig> output;
-  for (int i = 0; i < static_cast<int>(array.size()); ++i) {
-    auto &c = array[i];
-    StreamConfig s{c["processor_type"].asString(), c["primitive_type"].asString(),
-                   c["source_id"].asUInt(), c["tcp_dest_port"].asUInt()};
-    output.emplace_back(s);
-  }
-  return output;
-}
-
 Config::Config(std::string_view filename)
     : dict_(filename),
       // Setup configs
@@ -94,8 +68,8 @@ Config::Config(std::string_view filename)
       min_log_severity_(ToLOG_LEVEL(dict_.Get("log_min_severity"))),
       // Run input configs
       num_orbits_per_packet_(dict_.Get<uint64_t>("nOrbitsPerPacket")),
-      input_files_(dict_.Get<std::vector<std::string>>("input_files")),
-      input_streams_(dict_.Get<std::vector<StreamConfig>>("input_streams")),
+      input_files_(dict_.GetArray<std::string>("input_files")),
+      input_streams_(dict_.GetArray<StreamConfig>("input_streams")),
       // Run processor configs
       enable_processing_(dict_.Get<bool>("enable_stream_processor")),
       apply_zero_suppression_(dict_.Get<bool>("doZS")),
diff --git a/src/config.h b/src/config.h
index 868edc05f4aac47d06029c3b528a445241e64fd1..58453dc7cb0557d344b6d9fe72b26d91f319b321 100644
--- a/src/config.h
+++ b/src/config.h
@@ -13,6 +13,29 @@
 
 #include "log.h"
 
+class StreamConfig {
+ public:
+  const std::string processor_name_;
+  const std::string primitive_name_;
+  const uint32_t source_id_;
+  const uint32_t tcp_dest_port_;
+
+  StreamConfig(const std::string processor, const std::string primitive, uint32_t source_id,
+               uint32_t tcp_port)
+      : processor_name_(processor),
+        primitive_name_(primitive),
+        source_id_(source_id),
+        tcp_dest_port_(tcp_port) {}
+
+  friend std::ostream &operator<<(std::ostream &os, const StreamConfig &input) {
+    os << "processor: " << input.processor_name_ << std::endl;
+    os << "primitive: " << input.primitive_name_ << std::endl;
+    os << "source_id: " << input.source_id_ << std::endl;
+    os << "tcp_dest_port: " << input.tcp_dest_port_ << std::endl;
+    return os;
+  }
+};
+
 class ConfigMap {
  public:
   enum class EFormat { JSON5 };
@@ -38,33 +61,70 @@ class ConfigMap {
     return os;
   }
 
+  template <typename T = std::string>
+  T Get(const std::string &key, ValueType &node) {
+    const ValueType value = at(key, node);
+    try {
+      return ConvertValue<T>(value);
+    } catch (std::exception &e) {
+      LOG(ERROR) << "Key: " << key << "| Value '" << value.asString()
+                 << "' | Conversion failed with exception: " << e.what();
+      throw;
+    }
+  }
+
   template <typename T = std::string>
   T Get(const std::string &key) {
-    const ValueType value = at(key);
-    const auto str_val = value.asString();
-    if constexpr (std::is_same_v<T, std::string>)
-      return str_val;
-    else if constexpr (std::is_same_v<T, bool>) {
-      return value;
-      //      std::string s(str_val);
-      //      boost::algorithm::to_lower(s);
-      //      return s == "true" || s == "yes";
-    } else
+    return Get<T>(key, data_);
+  }
+
+  template <typename T>
+  std::vector<T> GetArray(const std::string &key) {
+    const ValueType array = at(key, data_);
+    std::vector<T> output;
+    for (int i = 0; i < static_cast<int>(array.size()); ++i) {
       try {
-        return static_cast<T>(std::stol(str_val));
+        output.emplace_back(ConvertValue<T>(array[i]));
       } catch (std::exception &e) {
-        LOG(ERROR) << "Key: " << key << "| Value '" << str_val << "' | Conversion of '" << str_val
-                   << "' failed with exception: " << e.what();
+        LOG(ERROR) << "Key: " << key << "| Value '" << array[i].asString()
+                   << "' | Conversion failed with exception: " << e.what();
         throw;
       }
+    }
+    return output;
+  }
+
+  template <typename T>
+  T ConvertValue(const ValueType &value) {
+    if constexpr (std::is_same_v<T, StreamConfig>) {
+      return StreamConfig(value["processor_type"].asString(), value["primitive_type"].asString(),
+                          value["source_id"].asUInt(), value["tcp_dest_port"].asUInt());
+    } else {
+      std::string str(value.asString());
+      if constexpr (std::is_same_v<T, std::string>)
+        return str;
+      else if constexpr (std::is_same_v<T, bool>) {
+        // Special logic for booleans
+        boost::algorithm::to_lower(str);
+        return str == "true" || str == "yes";
+      } else if constexpr (std::is_same_v<T, uint32_t>) {
+        return static_cast<uint32_t>(std::stoul(str));
+      } else if constexpr (std::is_same_v<T, uint64_t>) {
+        return static_cast<uint32_t>(std::stoull(str));
+      } else if constexpr (std::is_same_v<T, int>) {
+        return static_cast<int>(std::stoi(str));
+      } else {
+        throw std::runtime_error("Failed to convert value '" + str + "'.");
+      }
+    }
   }
 
  private:
   ValueType data_;
 
-  inline ValueType at(const std::string &key) const {
+  inline ValueType at(const std::string &key, const ValueType &node) const {
     try {
-      const auto &val = data_[key];
+      const auto &val = node[key];
       return val;
     } catch (std::exception &e) {
       LOG(ERROR) << "Error fetching value for key '" << key << "'";
@@ -178,29 +238,6 @@ class Config {
   }
 };
 
-class StreamConfig {
- public:
-  const std::string processor_name_;
-  const std::string primitive_name_;
-  const uint32_t source_id_;
-  const uint32_t tcp_dest_port_;
-
-  StreamConfig(const std::string &processor, const std::string &primitive, uint32_t source_id,
-               uint32_t tcp_port)
-      : processor_name_(processor),
-        primitive_name_(primitive),
-        source_id_(source_id),
-        tcp_dest_port_(tcp_port) {}
-
-  friend std::ostream &operator<<(std::ostream &os, const StreamConfig &input) {
-    os << "processor: " << input.processor_name_ << std::endl;
-    os << "primitive: " << input.primitive_name_ << std::endl;
-    os << "source_id: " << input.source_id_ << std::endl;
-    os << "tcp_dest_port: " << input.tcp_dest_port_ << std::endl;
-    return os;
-  }
-};
-
 // TODO(@glazzari): Provisionally gimped implementation of `ConfigView`
 class ConfigView {
  public: