diff --git a/Det/LbDD4hep/CMakeLists.txt b/Det/LbDD4hep/CMakeLists.txt
index 5afb19239c9bb0c2ce2196edc9b82feeb371a59b..f61ead21aa87b59723a54df010769fd78b0889f9 100644
--- a/Det/LbDD4hep/CMakeLists.txt
+++ b/Det/LbDD4hep/CMakeLists.txt
@@ -22,6 +22,8 @@ if(USE_DD4HEP)
             Gaudi::GaudiAlgLib
             Gaudi::GaudiKernel
             LHCb::LHCbKernel
+            nlohmann_json::nlohmann_json
+            yaml-cpp
     )
 
     if(DD4hep_ROOT)
diff --git a/Det/LbDD4hep/include/LbDD4hep/ConditionAccessorHolder.h b/Det/LbDD4hep/include/LbDD4hep/ConditionAccessorHolder.h
index 946d4648d4fe6d4999a4c0da3e3481c8194f419e..85b806b4ff62173e070e301e2c8899c2dc89ef64 100644
--- a/Det/LbDD4hep/include/LbDD4hep/ConditionAccessorHolder.h
+++ b/Det/LbDD4hep/include/LbDD4hep/ConditionAccessorHolder.h
@@ -21,6 +21,7 @@
 #include <GaudiKernel/detected.h>
 #include <Kernel/STLExtensions.h>
 #include <LbDD4hep/IDD4hepSvc.h>
+#include <LbDD4hep/utils.h>
 #include <any>
 #include <stdexcept>
 #include <type_traits>
@@ -139,7 +140,9 @@ namespace LHCb::Det::LbDD4hep {
           return T( cond );
         } else {
           using DT = std::decay_t<T>;
-          if constexpr ( !detail::PassAsAny<DT>::value ) {
+          if constexpr ( std::is_same_v<DT, nlohmann::json> ) {
+            return utils::y2j( cond.get<YAML::Node>() );
+          } else if constexpr ( !detail::PassAsAny<DT>::value ) {
             return cond.get<DT>();
           } else {
             const DT* p = nullptr;
diff --git a/Det/LbDD4hep/include/LbDD4hep/IDD4hepSvc.h b/Det/LbDD4hep/include/LbDD4hep/IDD4hepSvc.h
index 6186c49d2a312b3cbc20f776ebcec1cf59702ab6..934a8fb3bd4b1273b0717c402a60d5e0e43b4086 100644
--- a/Det/LbDD4hep/include/LbDD4hep/IDD4hepSvc.h
+++ b/Det/LbDD4hep/include/LbDD4hep/IDD4hepSvc.h
@@ -20,6 +20,7 @@
 #include <DDCond/ConditionsSlice.h>
 #include <GaudiKernel/IService.h>
 #include <Kernel/STLExtensions.h>
+#include <LbDD4hep/utils.h>
 #include <any>
 #include <boost/callable_traits.hpp>
 #include <cstdint>
@@ -126,7 +127,9 @@ namespace LHCb::Det::LbDD4hep {
           return Input( cond );
         } else {
           using DT = std::decay_t<Input>;
-          if constexpr ( !PassAsAny<DT>::value ) {
+          if constexpr ( std::is_same_v<DT, nlohmann::json> ) {
+            return utils::y2j( cond.get<YAML::Node>() );
+          } else if constexpr ( !PassAsAny<DT>::value ) {
             return cond.get<DT>();
           } else {
             const DT* p = nullptr;
diff --git a/Det/LbDD4hep/include/LbDD4hep/utils.h b/Det/LbDD4hep/include/LbDD4hep/utils.h
new file mode 100644
index 0000000000000000000000000000000000000000..06c2fb01b05ba59c7dd2a408a8354615435287c1
--- /dev/null
+++ b/Det/LbDD4hep/include/LbDD4hep/utils.h
@@ -0,0 +1,72 @@
+/*****************************************************************************\
+* (c) Copyright 2022 CERN for the benefit of the LHCb Collaboration           *
+*                                                                             *
+* This software is distributed under the terms of the GNU General Public      *
+* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   *
+*                                                                             *
+* In applying this licence, CERN does not waive the privileges and immunities *
+* granted to it by virtue of its status as an Intergovernmental Organization  *
+* or submit itself to any jurisdiction.                                       *
+\*****************************************************************************/
+#pragma once
+
+#include <algorithm>
+#include <cctype>
+#include <nlohmann/json.hpp>
+#include <string>
+#include <yaml-cpp/yaml.h>
+
+namespace LHCb::Det::LbDD4hep::utils {
+  /// Convert a YAML::Node instance to a nlohmann::json object.
+  ///
+  /// Since yaml-cpp does not make any assumption about [YAML untagged
+  /// nodes](https://yaml.org/spec/1.2.2/#resolved-tags) leaving it to the application to decide how to interprete the
+  /// values, this conversion function tries to map the value to bool, int64_t or double on a best effort basis, falling
+  /// back on std::string in case of failure.
+  inline nlohmann::json y2j( const YAML::Node& y ) {
+    nlohmann::json j;
+    switch ( y.Type() ) {
+    case YAML::NodeType::Sequence: {
+      j = nlohmann::json::array();
+      for ( const auto& element : y ) { j.push_back( y2j( element ) ); }
+    } break;
+    case YAML::NodeType::Map: {
+      j = nlohmann::json::object();
+      for ( const auto& entry : y ) { j[entry.first.as<std::string>()] = y2j( entry.second ); }
+    } break;
+    case YAML::NodeType::Scalar: {
+      auto tmp = y.as<std::string>();
+      j        = tmp; // implicit default: fall back on a string
+      if ( tmp.empty() ) {
+        // just an empty string is OK
+      } else if ( tmp == "true" ) {
+        j = true;
+      } else if ( tmp == "false" ) {
+        j = false;
+      } else { // if it's not a boolean literal, we try with numbers
+        try {
+          j = y.as<std::int64_t>();
+        } catch ( YAML::BadConversion& ) {
+          try {
+            j = y.as<double>();
+          } catch ( YAML::BadConversion& ) {
+            // not an int, not a float, we can only fall back on string
+          }
+        }
+      }
+    } break;
+    case YAML::NodeType::Undefined:
+    case YAML::NodeType::Null:
+    default: {
+      // nothing to do in these cases
+    }
+    }
+    return j;
+  }
+
+  /// Convert a nlohmann::json object to a YAML::Node instance.
+  ///
+  /// This function relies on YAML syntax being a superset of JSON, so we serialize
+  /// and deserialize.
+  inline YAML::Node j2y( const nlohmann::json& j ) { return YAML::Load( j.dump() ); }
+} // namespace LHCb::Det::LbDD4hep::utils