Boost::urls::format

Boost 1.82 dropped a lovely new toy, boost::urls::format, which is a lot
like our urlFromPieces method, but better in that it makes the resulting
uris more readable, and allows doing things like fragments in a single
line instead of multiple.  We should prefer it in some cases.

Tested:
Redfish service validator passes.
Spot checks of URLs work as expected.
Unit tests pass.

Signed-off-by: Ed Tanous <edtanous@google.com>
Change-Id: Ia7b38f0a95771c862507e7d5b4aa68aa1c98403c
diff --git a/redfish-core/lib/aggregation_service.hpp b/redfish-core/lib/aggregation_service.hpp
index 83953fd..9874d14 100644
--- a/redfish-core/lib/aggregation_service.hpp
+++ b/redfish-core/lib/aggregation_service.hpp
@@ -8,6 +8,7 @@
 #include "redfish_aggregator.hpp"
 #include "registries/privilege_registry.hpp"
 
+#include <boost/url/format.hpp>
 #include <nlohmann/json.hpp>
 
 #include <functional>
@@ -78,9 +79,8 @@
     for (const auto& sat : satelliteInfo)
     {
         nlohmann::json::object_t member;
-        member["@odata.id"] =
-            crow::utility::urlFromPieces("redfish", "v1", "AggregationService",
-                                         "AggregationSources", sat.first);
+        member["@odata.id"] = boost::urls::format(
+            "/redfish/v1/AggregationService/AggregationSources/{}", sat.first);
         members.emplace_back(std::move(member));
     }
     asyncResp->res.jsonValue["Members@odata.count"] = members.size();
@@ -160,9 +160,9 @@
         return;
     }
 
-    asyncResp->res.jsonValue["@odata.id"] =
-        crow::utility::urlFromPieces("redfish", "v1", "AggregationService",
-                                     "AggregationSources", aggregationSourceId);
+    asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
+        "/redfish/v1/AggregationService/AggregationSources/{}",
+        aggregationSourceId);
     asyncResp->res.jsonValue["@odata.type"] =
         "#AggregationSource.v1_3_1.AggregationSource";
     asyncResp->res.jsonValue["Id"] = aggregationSourceId;
diff --git a/redfish-core/lib/cable.hpp b/redfish-core/lib/cable.hpp
index 423ea9d..87e41d53 100644
--- a/redfish-core/lib/cable.hpp
+++ b/redfish-core/lib/cable.hpp
@@ -8,6 +8,7 @@
 #include "utils/json_utils.hpp"
 
 #include <boost/system/error_code.hpp>
+#include <boost/url/format.hpp>
 #include <sdbusplus/asio/property.hpp>
 #include <sdbusplus/unpack_properties.hpp>
 
@@ -151,8 +152,7 @@
 
                 asyncResp->res.jsonValue["@odata.type"] = "#Cable.v1_0_0.Cable";
                 asyncResp->res.jsonValue["@odata.id"] =
-                    crow::utility::urlFromPieces("redfish", "v1", "Cables",
-                                                 cableId);
+                    boost::urls::format("/redfish/v1/Cables/{}", cableId);
                 asyncResp->res.jsonValue["Id"] = cableId;
                 asyncResp->res.jsonValue["Name"] = "Cable";
 
diff --git a/redfish-core/lib/certificate_service.hpp b/redfish-core/lib/certificate_service.hpp
index 5fe9008..027e05d 100644
--- a/redfish-core/lib/certificate_service.hpp
+++ b/redfish-core/lib/certificate_service.hpp
@@ -12,6 +12,7 @@
 #include "utils/time_utils.hpp"
 
 #include <boost/system/linux_error.hpp>
+#include <boost/url/format.hpp>
 #include <sdbusplus/asio/property.hpp>
 #include <sdbusplus/bus/match.hpp>
 #include <sdbusplus/unpack_properties.hpp>
@@ -247,21 +248,20 @@
             boost::urls::url certURL;
             if (objPath.parent_path() == certs::httpsObjectPath)
             {
-                certURL = crow::utility::urlFromPieces(
-                    "redfish", "v1", "Managers", "bmc", "NetworkProtocol",
-                    "HTTPS", "Certificates", certId);
+                certURL = boost::urls::format(
+                    "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/{}",
+                    certId);
             }
             else if (objPath.parent_path() == certs::ldapObjectPath)
             {
-                certURL = crow::utility::urlFromPieces("redfish", "v1",
-                                                       "AccountService", "LDAP",
-                                                       "Certificates", certId);
+                certURL = boost::urls::format(
+                    "/redfish/v1/AccountService/LDAP/Certificates/{}", certId);
             }
             else if (objPath.parent_path() == certs::authorityObjectPath)
             {
-                certURL = crow::utility::urlFromPieces(
-                    "redfish", "v1", "Managers", "bmc", "Truststore",
-                    "Certificates", certId);
+                certURL = boost::urls::format(
+                    "/redfish/v1/Managers/bmc/Truststore/Certificates/{}",
+                    certId);
             }
             else
             {
@@ -932,9 +932,9 @@
 
         sdbusplus::message::object_path path(objectPath);
         std::string certId = path.filename();
-        const boost::urls::url certURL = crow::utility::urlFromPieces(
-            "redfish", "v1", "Managers", "bmc", "NetworkProtocol", "HTTPS",
-            "Certificates", certId);
+        const boost::urls::url certURL = boost::urls::format(
+            "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/{}",
+            certId);
         getCertificateProperties(asyncResp, objectPath, certs::httpsServiceName,
                                  certId, certURL, "HTTPS Certificate");
         BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
@@ -954,9 +954,8 @@
     }
 
     BMCWEB_LOG_DEBUG << "HTTPS Certificate ID=" << id;
-    const boost::urls::url certURL = crow::utility::urlFromPieces(
-        "redfish", "v1", "Managers", "bmc", "NetworkProtocol", "HTTPS",
-        "Certificates", id);
+    const boost::urls::url certURL = boost::urls::format(
+        "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/{}", id);
     std::string objPath =
         sdbusplus::message::object_path(certs::httpsObjectPath) / id;
     getCertificateProperties(asyncResp, objPath, certs::httpsServiceName, id,
@@ -1039,8 +1038,8 @@
 
         sdbusplus::message::object_path path(objectPath);
         std::string certId = path.filename();
-        const boost::urls::url certURL = crow::utility::urlFromPieces(
-            "redfish", "v1", "AccountService", "LDAP", "Certificates", certId);
+        const boost::urls::url certURL = boost::urls::format(
+            "/redfish/v1/AccountService/LDAP/Certificates/{}", certId);
         getCertificateProperties(asyncResp, objectPath, certs::ldapServiceName,
                                  certId, certURL, "LDAP Certificate");
         BMCWEB_LOG_DEBUG << "LDAP certificate install file="
@@ -1060,8 +1059,8 @@
     }
 
     BMCWEB_LOG_DEBUG << "LDAP Certificate ID=" << id;
-    const boost::urls::url certURL = crow::utility::urlFromPieces(
-        "redfish", "v1", "AccountService", "LDAP", "Certificates", id);
+    const boost::urls::url certURL = boost::urls::format(
+        "/redfish/v1/AccountService/LDAP/Certificates/{}", id);
     std::string objPath =
         sdbusplus::message::object_path(certs::ldapObjectPath) / id;
     getCertificateProperties(asyncResp, objPath, certs::ldapServiceName, id,
@@ -1160,9 +1159,8 @@
 
         sdbusplus::message::object_path path(objectPath);
         std::string certId = path.filename();
-        const boost::urls::url certURL =
-            crow::utility::urlFromPieces("redfish", "v1", "Managers", "bmc",
-                                         "Truststore", "Certificates", certId);
+        const boost::urls::url certURL = boost::urls::format(
+            "/redfish/v1/Managers/bmc/Truststore/Certificates/{}", certId);
         getCertificateProperties(asyncResp, objectPath,
                                  certs::authorityServiceName, certId, certURL,
                                  "TrustStore Certificate");
@@ -1183,8 +1181,8 @@
     }
 
     BMCWEB_LOG_DEBUG << "Truststore Certificate ID=" << id;
-    const boost::urls::url certURL = crow::utility::urlFromPieces(
-        "redfish", "v1", "Managers", "bmc", "Truststore", "Certificates", id);
+    const boost::urls::url certURL = boost::urls::format(
+        "/redfish/v1/Managers/bmc/Truststore/Certificates/{}", id);
     std::string objPath =
         sdbusplus::message::object_path(certs::authorityObjectPath) / id;
     getCertificateProperties(asyncResp, objPath, certs::authorityServiceName,
diff --git a/redfish-core/lib/chassis.hpp b/redfish-core/lib/chassis.hpp
index dc6afd8..a274421 100644
--- a/redfish-core/lib/chassis.hpp
+++ b/redfish-core/lib/chassis.hpp
@@ -26,6 +26,7 @@
 #include "utils/json_utils.hpp"
 
 #include <boost/system/error_code.hpp>
+#include <boost/url/format.hpp>
 #include <sdbusplus/asio/property.hpp>
 #include <sdbusplus/unpack_properties.hpp>
 
@@ -273,21 +274,18 @@
             asyncResp->res.jsonValue["@odata.type"] =
                 "#Chassis.v1_22_0.Chassis";
             asyncResp->res.jsonValue["@odata.id"] =
-                crow::utility::urlFromPieces("redfish", "v1", "Chassis",
-                                             chassisId);
+                boost::urls::format("/redfish/v1/Chassis/{}", chassisId);
             asyncResp->res.jsonValue["Name"] = "Chassis Collection";
             asyncResp->res.jsonValue["ChassisType"] = "RackMount";
             asyncResp->res.jsonValue["Actions"]["#Chassis.Reset"]["target"] =
-                crow::utility::urlFromPieces("redfish", "v1", "Chassis",
-                                             chassisId, "Actions",
-                                             "Chassis.Reset");
+                boost::urls::format(
+                    "/redfish/v1/Chassis/{}/Actions/Chassis.Reset", chassisId);
             asyncResp->res
                 .jsonValue["Actions"]["#Chassis.Reset"]["@Redfish.ActionInfo"] =
-                crow::utility::urlFromPieces("redfish", "v1", "Chassis",
-                                             chassisId, "ResetActionInfo");
+                boost::urls::format("/redfish/v1/Chassis/{}/ResetActionInfo",
+                                    chassisId);
             asyncResp->res.jsonValue["PCIeDevices"]["@odata.id"] =
-                crow::utility::urlFromPieces("redfish", "v1", "Systems",
-                                             "system", "PCIeDevices");
+                "/redfish/v1/Systems/system/PCIeDevices";
 
             dbus::utility::getAssociationEndPoints(
                 path + "/drive",
@@ -300,8 +298,8 @@
                 }
 
                 nlohmann::json reference;
-                reference["@odata.id"] = crow::utility::urlFromPieces(
-                    "redfish", "v1", "Chassis", chassisId, "Drives");
+                reference["@odata.id"] = boost::urls::format(
+                    "/redfish/v1/Chassis/{}/Drives", chassisId);
                 asyncResp->res.jsonValue["Drives"] = std::move(reference);
                 });
 
@@ -425,29 +423,28 @@
                 asyncResp->res.jsonValue["Id"] = chassisId;
 #ifdef BMCWEB_ALLOW_DEPRECATED_POWER_THERMAL
                 asyncResp->res.jsonValue["Thermal"]["@odata.id"] =
-                    crow::utility::urlFromPieces("redfish", "v1", "Chassis",
-                                                 chassisId, "Thermal");
+                    boost::urls::format("/redfish/v1/Chassis/{}/Thermal",
+                                        chassisId);
                 // Power object
                 asyncResp->res.jsonValue["Power"]["@odata.id"] =
-                    crow::utility::urlFromPieces("redfish", "v1", "Chassis",
-                                                 chassisId, "Power");
+                    boost::urls::format("/redfish/v1/Chassis/{}/Power",
+                                        chassisId);
 #endif
 #ifdef BMCWEB_NEW_POWERSUBSYSTEM_THERMALSUBSYSTEM
                 asyncResp->res.jsonValue["ThermalSubsystem"]["@odata.id"] =
-                    crow::utility::urlFromPieces("redfish", "v1", "Chassis",
-                                                 chassisId, "ThermalSubsystem");
+                    boost::urls::format(
+                        "/redfish/v1/Chassis/{}/ThermalSubsystem", chassisId);
                 asyncResp->res.jsonValue["PowerSubsystem"]["@odata.id"] =
-                    crow::utility::urlFromPieces("redfish", "v1", "Chassis",
-                                                 chassisId, "PowerSubsystem");
+                    boost::urls::format("/redfish/v1/Chassis/{}/PowerSubsystem",
+                                        chassisId);
                 asyncResp->res.jsonValue["EnvironmentMetrics"]["@odata.id"] =
-                    crow::utility::urlFromPieces("redfish", "v1", "Chassis",
-                                                 chassisId,
-                                                 "EnvironmentMetrics");
+                    boost::urls::format(
+                        "/redfish/v1/Chassis/{}/EnvironmentMetrics", chassisId);
 #endif
                 // SensorCollection
                 asyncResp->res.jsonValue["Sensors"]["@odata.id"] =
-                    crow::utility::urlFromPieces("redfish", "v1", "Chassis",
-                                                 chassisId, "Sensors");
+                    boost::urls::format("/redfish/v1/Chassis/{}/Sensors",
+                                        chassisId);
                 asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
 
                 nlohmann::json::array_t computerSystems;
@@ -737,8 +734,8 @@
         return;
     }
     asyncResp->res.jsonValue["@odata.type"] = "#ActionInfo.v1_1_2.ActionInfo";
-    asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
-        "redfish", "v1", "Chassis", chassisId, "ResetActionInfo");
+    asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
+        "/redfish/v1/Chassis/{}/ResetActionInfo", chassisId);
     asyncResp->res.jsonValue["Name"] = "Reset Action Info";
 
     asyncResp->res.jsonValue["Id"] = "ResetActionInfo";
diff --git a/redfish-core/lib/environment_metrics.hpp b/redfish-core/lib/environment_metrics.hpp
index fd7668e..32a2d09 100644
--- a/redfish-core/lib/environment_metrics.hpp
+++ b/redfish-core/lib/environment_metrics.hpp
@@ -5,6 +5,8 @@
 #include "registries/privilege_registry.hpp"
 #include "utils/chassis_utils.hpp"
 
+#include <boost/url/format.hpp>
+
 #include <memory>
 #include <optional>
 #include <string>
@@ -64,8 +66,8 @@
             "#EnvironmentMetrics.v1_3_0.EnvironmentMetrics";
         asyncResp->res.jsonValue["Name"] = "Chassis Environment Metrics";
         asyncResp->res.jsonValue["Id"] = "EnvironmentMetrics";
-        asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
-            "redfish", "v1", "Chassis", chassisId, "EnvironmentMetrics");
+        asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
+            "/redfish/v1/Chassis/{}/EnvironmentMetrics", chassisId);
     };
 
     redfish::chassis_utils::getValidChassisPath(asyncResp, chassisId,
diff --git a/redfish-core/lib/ethernet.hpp b/redfish-core/lib/ethernet.hpp
index 0ea53e2..93c475e 100644
--- a/redfish-core/lib/ethernet.hpp
+++ b/redfish-core/lib/ethernet.hpp
@@ -28,6 +28,7 @@
 #include <boost/algorithm/string/classification.hpp>
 #include <boost/algorithm/string/split.hpp>
 #include <boost/container/flat_set.hpp>
+#include <boost/url/format.hpp>
 
 #include <array>
 #include <optional>
@@ -1576,8 +1577,8 @@
 
     nlohmann::json& jsonResponse = asyncResp->res.jsonValue;
     jsonResponse["Id"] = ifaceId;
-    jsonResponse["@odata.id"] = crow::utility::urlFromPieces(
-        "redfish", "v1", "Managers", "bmc", "EthernetInterfaces", ifaceId);
+    jsonResponse["@odata.id"] = boost::urls::format(
+        "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", ifaceId);
     jsonResponse["InterfaceEnabled"] = ethData.nicEnabled;
 
     auto health = std::make_shared<HealthPopulate>(asyncResp);
@@ -1638,9 +1639,8 @@
         jsonResponse["FQDN"] = fqdn;
     }
 
-    jsonResponse["VLANs"]["@odata.id"] =
-        crow::utility::urlFromPieces("redfish", "v1", "Managers", "bmc",
-                                     "EthernetInterfaces", ifaceId, "VLANs");
+    jsonResponse["VLANs"]["@odata.id"] = boost::urls::format(
+        "/redfish/v1/Managers/bmc/EthernetInterfaces/{}/VLANs", ifaceId);
 
     jsonResponse["NameServers"] = ethData.nameServers;
     jsonResponse["StaticNameServers"] = ethData.staticNameServers;
@@ -1750,9 +1750,9 @@
                 if (found == std::string::npos)
                 {
                     nlohmann::json::object_t iface;
-                    iface["@odata.id"] = crow::utility::urlFromPieces(
-                        "redfish", "v1", "Managers", "bmc",
-                        "EthernetInterfaces", ifaceItem);
+                    iface["@odata.id"] = boost::urls::format(
+                        "/redfish/v1/Managers/bmc/EthernetInterfaces/{}",
+                        ifaceItem);
                     ifaceArray.emplace_back(std::move(iface));
                 }
             }
@@ -1983,10 +1983,9 @@
             if (success && ethData.vlanId)
             {
                 asyncResp->res.jsonValue["Id"] = ifaceId;
-                asyncResp->res.jsonValue["@odata.id"] =
-                    crow::utility::urlFromPieces(
-                        "redfish", "v1", "Managers", "bmc",
-                        "EthernetInterfaces", parentIfaceId, "VLANs", ifaceId);
+                asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
+                    "/redfish/v1/Managers/bmc/EthernetInterfaces/{}/VLANs/{}",
+                    parentIfaceId, ifaceId);
 
                 asyncResp->res.jsonValue["VLANEnable"] = ethData.nicEnabled;
                 asyncResp->res.jsonValue["VLANId"] = *ethData.vlanId;
@@ -2172,20 +2171,18 @@
                 if (ifaceItem.starts_with(rootInterfaceName + "_"))
                 {
                     nlohmann::json::object_t iface;
-                    iface["@odata.id"] = crow::utility::urlFromPieces(
-                        "redfish", "v1", "Managers", "bmc",
-                        "EthernetInterfaces", rootInterfaceName, "VLANs",
-                        ifaceItem);
+                    iface["@odata.id"] = boost::urls::format(
+                        "/redfish/v1/Managers/bmc/EthernetInterfaces/{}/VLANs/{}",
+                        rootInterfaceName, ifaceItem);
                     ifaceArray.emplace_back(std::move(iface));
                 }
             }
 
             asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size();
             asyncResp->res.jsonValue["Members"] = std::move(ifaceArray);
-            asyncResp->res.jsonValue["@odata.id"] =
-                crow::utility::urlFromPieces("redfish", "v1", "Managers", "bmc",
-                                             "EthernetInterfaces",
-                                             rootInterfaceName, "VLANs");
+            asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
+                "/redfish/v1/Managers/bmc/EthernetInterfaces/{}/VLANs",
+                rootInterfaceName);
         });
         });
 
diff --git a/redfish-core/lib/fabric_adapters.hpp b/redfish-core/lib/fabric_adapters.hpp
index be89fbc..16174bf 100644
--- a/redfish-core/lib/fabric_adapters.hpp
+++ b/redfish-core/lib/fabric_adapters.hpp
@@ -9,6 +9,7 @@
 #include "utils/json_utils.hpp"
 
 #include <boost/system/error_code.hpp>
+#include <boost/url/format.hpp>
 #include <sdbusplus/asio/property.hpp>
 #include <sdbusplus/unpack_properties.hpp>
 
@@ -184,8 +185,8 @@
     aResp->res.jsonValue["@odata.type"] = "#FabricAdapter.v1_4_0.FabricAdapter";
     aResp->res.jsonValue["Name"] = "Fabric Adapter";
     aResp->res.jsonValue["Id"] = adapterId;
-    aResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
-        "redfish", "v1", "Systems", systemName, "FabricAdapters", adapterId);
+    aResp->res.jsonValue["@odata.id"] = boost::urls::format(
+        "/redfish/v1/Systems/{}/FabricAdapters/{}", systemName, adapterId);
 
     aResp->res.jsonValue["Status"]["State"] = "Enabled";
     aResp->res.jsonValue["Status"]["Health"] = "OK";
@@ -283,8 +284,8 @@
     aResp->res.jsonValue["@odata.type"] =
         "#FabricAdapterCollection.FabricAdapterCollection";
     aResp->res.jsonValue["Name"] = "Fabric Adapter Collection";
-    aResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
-        "redfish", "v1", "Systems", systemName, "FabricAdapters");
+    aResp->res.jsonValue["@odata.id"] = boost::urls::format(
+        "/redfish/v1/Systems/{}/FabricAdapters", systemName);
 
     constexpr std::array<std::string_view, 1> interfaces{
         "xyz.openbmc_project.Inventory.Item.FabricAdapter"};
diff --git a/redfish-core/lib/hypervisor_system.hpp b/redfish-core/lib/hypervisor_system.hpp
index 84563ba..c87b7ef 100644
--- a/redfish-core/lib/hypervisor_system.hpp
+++ b/redfish-core/lib/hypervisor_system.hpp
@@ -11,6 +11,7 @@
 #include "utils/json_utils.hpp"
 
 #include <boost/container/flat_set.hpp>
+#include <boost/url/format.hpp>
 #include <sdbusplus/asio/property.hpp>
 
 #include <array>
@@ -482,9 +483,8 @@
     const boost::container::flat_set<IPv4AddressData>& ipv4Data)
 {
     jsonResponse["Id"] = ifaceId;
-    jsonResponse["@odata.id"] =
-        crow::utility::urlFromPieces("redfish", "v1", "Systems", "hypervisor",
-                                     "EthernetInterfaces", ifaceId);
+    jsonResponse["@odata.id"] = boost::urls::format(
+        "/redfish/v1/Systems/hypervisor/EthernetInterfaces/{}", ifaceId);
     jsonResponse["InterfaceEnabled"] = true;
     jsonResponse["MACAddress"] = ethData.macAddress;
 
@@ -761,9 +761,8 @@
                 continue;
             }
             nlohmann::json::object_t ethIface;
-            ethIface["@odata.id"] = crow::utility::urlFromPieces(
-                "redfish", "v1", "Systems", "hypervisor", "EthernetInterfaces",
-                name);
+            ethIface["@odata.id"] = boost::urls::format(
+                "/redfish/v1/Systems/hypervisor/EthernetInterfaces/{}", name);
             ifaceArray.emplace_back(std::move(ethIface));
         }
         asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size();
diff --git a/redfish-core/lib/log_services.hpp b/redfish-core/lib/log_services.hpp
index c6b1354..3bc4322 100644
--- a/redfish-core/lib/log_services.hpp
+++ b/redfish-core/lib/log_services.hpp
@@ -42,6 +42,7 @@
 #include <boost/beast/http/verb.hpp>
 #include <boost/container/flat_map.hpp>
 #include <boost/system/linux_error.hpp>
+#include <boost/url/format.hpp>
 #include <sdbusplus/asio/property.hpp>
 #include <sdbusplus/unpack_properties.hpp>
 
@@ -1339,9 +1340,9 @@
 
     // Fill in the log entry with the gathered data
     logEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
-    logEntryJson["@odata.id"] = crow::utility::urlFromPieces(
-        "redfish", "v1", "Systems", "system", "LogServices", "EventLog",
-        "Entries", logEntryID);
+    logEntryJson["@odata.id"] = boost::urls::format(
+        "/redfish/v1/Systems/system/LogServices/EventLog/Entries/{}",
+        logEntryID);
     logEntryJson["Name"] = "System Event Log Entry";
     logEntryJson["Id"] = logEntryID;
     logEntryJson["Message"] = std::move(msg);
@@ -1674,9 +1675,9 @@
                 entriesArray.push_back({});
                 nlohmann::json& thisEntry = entriesArray.back();
                 thisEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
-                thisEntry["@odata.id"] = crow::utility::urlFromPieces(
-                    "redfish", "v1", "Systems", "system", "LogServices",
-                    "EventLog", "Entries", std::to_string(*id));
+                thisEntry["@odata.id"] = boost::urls::format(
+                    "/redfish/v1/Systems/system/LogServices/EventLog/Entries/{}",
+                    std::to_string(*id));
                 thisEntry["Name"] = "System Event Log Entry";
                 thisEntry["Id"] = std::to_string(*id);
                 thisEntry["Message"] = *message;
@@ -1794,10 +1795,9 @@
 
             asyncResp->res.jsonValue["@odata.type"] =
                 "#LogEntry.v1_9_0.LogEntry";
-            asyncResp->res.jsonValue["@odata.id"] =
-                crow::utility::urlFromPieces(
-                    "redfish", "v1", "Systems", "system", "LogServices",
-                    "EventLog", "Entries", std::to_string(*id));
+            asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
+                "/redfish/v1/Systems/system/LogServices/EventLog/Entries/{}",
+                std::to_string(*id));
             asyncResp->res.jsonValue["Name"] = "System Event Log Entry";
             asyncResp->res.jsonValue["Id"] = std::to_string(*id);
             asyncResp->res.jsonValue["Message"] = *message;
@@ -2093,9 +2093,9 @@
 {
     // Fill in the log entry with the gathered data.
     logEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
-    logEntryJson["@odata.id"] = crow::utility::urlFromPieces(
-        "redfish", "v1", "Systems", "system", "LogServices", "HostLogger",
-        "Entries", logEntryID);
+    logEntryJson["@odata.id"] = boost::urls::format(
+        "/redfish/v1/Systems/system/LogServices/HostLogger/Entries/{}",
+        logEntryID);
     logEntryJson["Name"] = "Host Logger Entry";
     logEntryJson["Id"] = logEntryID;
     logEntryJson["Message"] = msg;
@@ -2441,8 +2441,8 @@
 
     // Fill in the log entry with the gathered data
     bmcJournalLogEntryJson["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
-    bmcJournalLogEntryJson["@odata.id"] = crow::utility::urlFromPieces(
-        "redfish", "v1", "Managers", "bmc", "LogServices", "Journal", "Entries",
+    bmcJournalLogEntryJson["@odata.id"] = boost::urls::format(
+        "/redfish/v1/Managers/bmc/LogServices/Journal/Entries/{}",
         bmcJournalLogEntryID);
     bmcJournalLogEntryJson["Name"] = "BMC Journal Entry";
     bmcJournalLogEntryJson["Id"] = bmcJournalLogEntryID;
@@ -3062,8 +3062,7 @@
             redfishDateTimeOffset.second;
 
         asyncResp->res.jsonValue["Entries"]["@odata.id"] =
-            crow::utility::urlFromPieces("redfish", "v1", "Systems", "system",
-                                         "LogServices", "Crashdump", "Entries");
+            "/redfish/v1/Systems/system/LogServices/Crashdump/Entries";
         asyncResp->res.jsonValue["Actions"]["#LogService.ClearLog"]["target"] =
             "/redfish/v1/Systems/system/LogServices/Crashdump/Actions/LogService.ClearLog";
         asyncResp->res.jsonValue["Actions"]["#LogService.CollectDiagnosticData"]
@@ -3147,9 +3146,9 @@
             logID + "/" + filename;
         nlohmann::json::object_t logEntry;
         logEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
-        logEntry["@odata.id"] = crow::utility::urlFromPieces(
-            "redfish", "v1", "Systems", "system", "LogServices", "Crashdump",
-            "Entries", logID);
+        logEntry["@odata.id"] = boost::urls::format(
+            "/redfish/v1/Systems/system/LogServices/Crashdump/Entries/{}",
+            logID);
         logEntry["Name"] = "CPU Crashdump";
         logEntry["Id"] = logID;
         logEntry["EntryType"] = "Oem";
@@ -3783,9 +3782,9 @@
         // Format entry
         nlohmann::json::object_t bmcLogEntry;
         bmcLogEntry["@odata.type"] = "#LogEntry.v1_9_0.LogEntry";
-        bmcLogEntry["@odata.id"] = crow::utility::urlFromPieces(
-            "redfish", "v1", "Systems", "system", "LogServices", "PostCodes",
-            "Entries", postcodeEntryID);
+        bmcLogEntry["@odata.id"] = boost::urls::format(
+            "/redfish/v1/Systems/system/LogServices/PostCodes/Entries/{}",
+            postcodeEntryID);
         bmcLogEntry["Name"] = "POST Code Log Entry";
         bmcLogEntry["Id"] = postcodeEntryID;
         bmcLogEntry["Message"] = std::move(msg);
diff --git a/redfish-core/lib/managers.hpp b/redfish-core/lib/managers.hpp
index 819a788..eb453f2 100644
--- a/redfish-core/lib/managers.hpp
+++ b/redfish-core/lib/managers.hpp
@@ -28,6 +28,7 @@
 #include "utils/time_utils.hpp"
 
 #include <boost/system/error_code.hpp>
+#include <boost/url/format.hpp>
 #include <sdbusplus/asio/property.hpp>
 #include <sdbusplus/unpack_properties.hpp>
 
@@ -392,8 +393,7 @@
                     }
                 }
 
-                boost::urls::url url = crow::utility::urlFromPieces(
-                    "redfish", "v1", "Managers", "bmc");
+                boost::urls::url url("/redfish/v1/Managers/bmc");
                 if (intfPair.first == pidZoneConfigurationIface)
                 {
                     std::string chassis;
@@ -403,8 +403,8 @@
                         chassis = "#IllegalValue";
                     }
                     nlohmann::json& zone = zones[name];
-                    zone["Chassis"]["@odata.id"] = crow::utility::urlFromPieces(
-                        "redfish", "v1", "Chassis", chassis);
+                    zone["Chassis"]["@odata.id"] =
+                        boost::urls::format("/redfish/v1/Chassis/{}", chassis);
                     url.set_fragment(
                         ("/Oem/OpenBmc/Fan/FanZones"_json_pointer / name)
                             .to_string());
@@ -584,10 +584,8 @@
                             {
                                 dbus::utility::escapePathForDbus(itemCopy);
                                 nlohmann::json::object_t input;
-                                boost::urls::url managerUrl =
-                                    crow::utility::urlFromPieces(
-                                        "redfish", "v1", "Managers", "bmc");
-                                managerUrl.set_fragment(
+                                boost::urls::url managerUrl = boost::urls::format(
+                                    "/redfish/v1/Managers/bmc#{}",
                                     ("/Oem/OpenBmc/Fan/FanZones"_json_pointer /
                                      itemCopy)
                                         .to_string());
@@ -826,9 +824,9 @@
         if (managedItem == nullptr)
         {
             BMCWEB_LOG_ERROR << "Failed to get chassis from config patch";
-            messages::invalidObject(response->res,
-                                    crow::utility::urlFromPieces(
-                                        "redfish", "v1", "Chassis", chassis));
+            messages::invalidObject(
+                response->res,
+                boost::urls::format("/redfish/v1/Chassis/{}", chassis));
             return CreatePIDRet::fail;
         }
     }
@@ -939,8 +937,8 @@
             {
                 BMCWEB_LOG_ERROR << "Failed to get chassis from config patch";
                 messages::invalidObject(
-                    response->res, crow::utility::urlFromPieces(
-                                       "redfish", "v1", "Chassis", chassis));
+                    response->res,
+                    boost::urls::format("/redfish/v1/Chassis/{}", chassis));
                 return CreatePIDRet::fail;
             }
             output.emplace_back("Zones", std::move(zonesStr));
@@ -1034,8 +1032,8 @@
             {
                 BMCWEB_LOG_ERROR << "Got invalid path " << chassisId;
                 messages::invalidObject(
-                    response->res, crow::utility::urlFromPieces(
-                                       "redfish", "v1", "Chassis", chassisId));
+                    response->res,
+                    boost::urls::format("/redfish/v1/Chassis/{}", chassisId));
                 return CreatePIDRet::fail;
             }
         }
@@ -1080,8 +1078,8 @@
             {
                 BMCWEB_LOG_ERROR << "Failed to get chassis from config patch";
                 messages::invalidObject(
-                    response->res, crow::utility::urlFromPieces(
-                                       "redfish", "v1", "Chassis", chassis));
+                    response->res,
+                    boost::urls::format("/redfish/v1/Chassis/{}", chassis));
                 return CreatePIDRet::fail;
             }
             output.emplace_back("Zones", std::move(zonesStrs));
@@ -1643,8 +1641,8 @@
                         BMCWEB_LOG_ERROR << "Failed to find chassis on dbus";
                         messages::resourceMissingAtURI(
                             response->res,
-                            crow::utility::urlFromPieces("redfish", "v1",
-                                                         "Chassis", chassis));
+                            boost::urls::format("/redfish/v1/Chassis/{}",
+                                                chassis));
                         return;
                     }
 
@@ -2023,8 +2021,8 @@
             aRsp->res.jsonValue["Links"]["ManagerForChassis@odata.count"] = 1;
             nlohmann::json::array_t managerForChassis;
             nlohmann::json::object_t managerObj;
-            boost::urls::url chassiUrl = crow::utility::urlFromPieces(
-                "redfish", "v1", "Chassis", chassisId);
+            boost::urls::url chassiUrl =
+                boost::urls::format("/redfish/v1/Chassis/{}", chassisId);
             managerObj["@odata.id"] = chassiUrl;
             managerForChassis.emplace_back(std::move(managerObj));
             aRsp->res.jsonValue["Links"]["ManagerForChassis"] =
diff --git a/redfish-core/lib/memory.hpp b/redfish-core/lib/memory.hpp
index c57d387..46b35d5 100644
--- a/redfish-core/lib/memory.hpp
+++ b/redfish-core/lib/memory.hpp
@@ -26,6 +26,7 @@
 #include "utils/json_utils.hpp"
 
 #include <boost/system/error_code.hpp>
+#include <boost/url/format.hpp>
 #include <nlohmann/json.hpp>
 #include <sdbusplus/asio/property.hpp>
 #include <sdbusplus/unpack_properties.hpp>
@@ -754,8 +755,8 @@
         }
         // Set @odata only if object is found
         aResp->res.jsonValue["@odata.type"] = "#Memory.v1_11_0.Memory";
-        aResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
-            "redfish", "v1", "Systems", "system", "Memory", dimmId);
+        aResp->res.jsonValue["@odata.id"] =
+            boost::urls::format("/redfish/v1/Systems/system/Memory/{}", dimmId);
         return;
         });
 }
diff --git a/redfish-core/lib/message_registries.hpp b/redfish-core/lib/message_registries.hpp
index ce147a8..ead4e38 100644
--- a/redfish-core/lib/message_registries.hpp
+++ b/redfish-core/lib/message_registries.hpp
@@ -24,6 +24,8 @@
 #include "registries/resource_event_message_registry.hpp"
 #include "registries/task_event_message_registry.hpp"
 
+#include <boost/url/format.hpp>
+
 #include <array>
 
 namespace redfish
@@ -53,8 +55,8 @@
          std::to_array({"Base", "TaskEvent", "ResourceEvent", "OpenBMC"}))
     {
         nlohmann::json::object_t member;
-        member["@odata.id"] = crow::utility::urlFromPieces(
-            "redfish", "v1", "Registries", memberName);
+        member["@odata.id"] = boost::urls::format("/redfish/v1/Registries/{}",
+                                                  memberName);
         members.emplace_back(std::move(member));
     }
 }
@@ -111,7 +113,7 @@
     }
 
     asyncResp->res.jsonValue["@odata.id"] =
-        crow::utility::urlFromPieces("redfish", "v1", "Registries", registry);
+        boost::urls::format("/redfish/v1/Registries/{}", registry);
     asyncResp->res.jsonValue["@odata.type"] =
         "#MessageRegistryFile.v1_1_0.MessageRegistryFile";
     asyncResp->res.jsonValue["Name"] = registry + " Message Registry File";
diff --git a/redfish-core/lib/metric_report.hpp b/redfish-core/lib/metric_report.hpp
index 7ae80d7..1f21c91 100644
--- a/redfish-core/lib/metric_report.hpp
+++ b/redfish-core/lib/metric_report.hpp
@@ -8,6 +8,7 @@
 #include "utils/telemetry_utils.hpp"
 #include "utils/time_utils.hpp"
 
+#include <boost/url/format.hpp>
 #include <sdbusplus/asio/property.hpp>
 
 #include <array>
@@ -45,12 +46,12 @@
                        const TimestampReadings& timestampReadings)
 {
     json["@odata.type"] = "#MetricReport.v1_3_0.MetricReport";
-    json["@odata.id"] = crow::utility::urlFromPieces(
-        "redfish", "v1", "TelemetryService", "MetricReports", id);
+    json["@odata.id"] = boost::urls::format(
+        "/redfish/v1/TelemetryService/MetricReports/{}", id);
     json["Id"] = id;
     json["Name"] = id;
-    json["MetricReportDefinition"]["@odata.id"] = crow::utility::urlFromPieces(
-        "redfish", "v1", "TelemetryService", "MetricReportDefinitions", id);
+    json["MetricReportDefinition"]["@odata.id"] = boost::urls::format(
+        "/redfish/v1/TelemetryService/MetricReportDefinitions/{}", id);
 
     const auto& [timestamp, readings] = timestampReadings;
     json["Timestamp"] = redfish::time_utils::getDateTimeUintMs(timestamp);
diff --git a/redfish-core/lib/metric_report_definition.hpp b/redfish-core/lib/metric_report_definition.hpp
index d5d60ed..7f8a29f 100644
--- a/redfish-core/lib/metric_report_definition.hpp
+++ b/redfish-core/lib/metric_report_definition.hpp
@@ -11,6 +11,7 @@
 #include "utils/time_utils.hpp"
 
 #include <boost/container/flat_map.hpp>
+#include <boost/url/format.hpp>
 #include <sdbusplus/asio/property.hpp>
 #include <sdbusplus/unpack_properties.hpp>
 
@@ -37,13 +38,12 @@
 {
     asyncResp->res.jsonValue["@odata.type"] =
         "#MetricReportDefinition.v1_3_0.MetricReportDefinition";
-    asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
-        "redfish", "v1", "TelemetryService", "MetricReportDefinitions", id);
+    asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
+        "/redfish/v1/TelemetryService/MetricReportDefinitions/{}", id);
     asyncResp->res.jsonValue["Id"] = id;
     asyncResp->res.jsonValue["Name"] = id;
-    asyncResp->res.jsonValue["MetricReport"]["@odata.id"] =
-        crow::utility::urlFromPieces("redfish", "v1", "TelemetryService",
-                                     "MetricReports", id);
+    asyncResp->res.jsonValue["MetricReport"]["@odata.id"] = boost::urls::format(
+        "/redfish/v1/TelemetryService/MetricReports/{}", id);
     asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
     asyncResp->res.jsonValue["ReportUpdates"] = "Overwrite";
 
diff --git a/redfish-core/lib/pcie.hpp b/redfish-core/lib/pcie.hpp
index 2754216..d0c88f4 100644
--- a/redfish-core/lib/pcie.hpp
+++ b/redfish-core/lib/pcie.hpp
@@ -25,6 +25,7 @@
 #include "utils/dbus_utils.hpp"
 
 #include <boost/system/linux_error.hpp>
+#include <boost/url/format.hpp>
 #include <sdbusplus/asio/property.hpp>
 #include <sdbusplus/unpack_properties.hpp>
 
@@ -127,8 +128,8 @@
                 continue;
             }
             nlohmann::json::object_t pcieDevice;
-            pcieDevice["@odata.id"] = crow::utility::urlFromPieces(
-                "redfish", "v1", "Systems", "system", "PCIeDevices", devName);
+            pcieDevice["@odata.id"] = boost::urls::format(
+                "/redfish/v1/Systems/system/PCIeDevices/{}", devName);
             pcieDeviceList.emplace_back(std::move(pcieDevice));
         }
         asyncResp->res.jsonValue[name + "@odata.count"] = pcieDeviceList.size();
@@ -354,9 +355,9 @@
         resp.jsonValue["PCIeInterface"]["LanesInUse"] = *lanesInUse;
     }
 
-    resp.jsonValue["PCIeFunctions"]["@odata.id"] = crow::utility::urlFromPieces(
-        "redfish", "v1", "Systems", "system", "PCIeDevices", pcieDeviceId,
-        "PCIeFunctions");
+    resp.jsonValue["PCIeFunctions"]["@odata.id"] = boost::urls::format(
+        "/redfish/v1/Systems/system/PCIeDevices/{}/PCIeFunctions",
+        pcieDeviceId);
 }
 
 inline void getPCIeDeviceProperties(
@@ -392,8 +393,8 @@
         boost::beast::http::field::link,
         "</redfish/v1/JsonSchemas/PCIeDevice/PCIeDevice.json>; rel=describedby");
     aResp->res.jsonValue["@odata.type"] = "#PCIeDevice.v1_9_0.PCIeDevice";
-    aResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
-        "redfish", "v1", "Systems", "system", "PCIeDevices", pcieDeviceId);
+    aResp->res.jsonValue["@odata.id"] = boost::urls::format(
+        "/redfish/v1/Systems/system/PCIeDevices/{}", pcieDeviceId);
     aResp->res.jsonValue["Name"] = "PCIe Device";
     aResp->res.jsonValue["Id"] = pcieDeviceId;
     aResp->res.jsonValue["Status"]["State"] = "Enabled";
@@ -468,9 +469,9 @@
         }
 
         nlohmann::json::object_t pcieFunction;
-        pcieFunction["@odata.id"] = crow::utility::urlFromPieces(
-            "redfish", "v1", "Systems", "system", "PCIeDevices", pcieDeviceId,
-            "PCIeFunctions", std::to_string(functionNum));
+        pcieFunction["@odata.id"] = boost::urls::format(
+            "/redfish/v1/Systems/system/PCIeDevices/{}/PCIeFunctions/{}",
+            pcieDeviceId, std::to_string(functionNum));
         pcieFunctionList.emplace_back(std::move(pcieFunction));
     }
     res.jsonValue["PCIeFunctions@odata.count"] = pcieFunctionList.size();
@@ -495,9 +496,9 @@
             "</redfish/v1/JsonSchemas/PCIeFunctionCollection/PCIeFunctionCollection.json>; rel=describedby");
         aResp->res.jsonValue["@odata.type"] =
             "#PCIeFunctionCollection.PCIeFunctionCollection";
-        aResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
-            "redfish", "v1", "Systems", "system", "PCIeDevices", pcieDeviceId,
-            "PCIeFunctions");
+        aResp->res.jsonValue["@odata.id"] = boost::urls::format(
+            "/redfish/v1/Systems/system/PCIeDevices/{}/PCIeFunctions",
+            pcieDeviceId);
         aResp->res.jsonValue["Name"] = "PCIe Function Collection";
         aResp->res.jsonValue["Description"] =
             "Collection of PCIe Functions for PCIe Device " + pcieDeviceId;
@@ -608,15 +609,14 @@
         boost::beast::http::field::link,
         "</redfish/v1/JsonSchemas/PCIeFunction/PCIeFunction.json>; rel=describedby");
     resp.jsonValue["@odata.type"] = "#PCIeFunction.v1_2_3.PCIeFunction";
-    resp.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
-        "redfish", "v1", "Systems", "system", "PCIeDevices", pcieDeviceId,
-        "PCIeFunctions", pcieFunctionId);
+    resp.jsonValue["@odata.id"] = boost::urls::format(
+        "/redfish/v1/Systems/system/PCIeDevices/{}/PCIeFunctions/{}",
+        pcieDeviceId, pcieFunctionId);
     resp.jsonValue["Name"] = "PCIe Function";
     resp.jsonValue["Id"] = pcieFunctionId;
     resp.jsonValue["FunctionId"] = std::stoi(pcieFunctionId);
-    resp.jsonValue["Links"]["PCIeDevice"]["@odata.id"] =
-        crow::utility::urlFromPieces("redfish", "v1", "Systems", "system",
-                                     "PCIeDevices", pcieDeviceId);
+    resp.jsonValue["Links"]["PCIeDevice"]["@odata.id"] = boost::urls::format(
+        "/redfish/v1/Systems/system/PCIeDevices/{}", pcieDeviceId);
 }
 
 inline void
diff --git a/redfish-core/lib/pcie_slots.hpp b/redfish-core/lib/pcie_slots.hpp
index 18301bf..ece84a3 100644
--- a/redfish-core/lib/pcie_slots.hpp
+++ b/redfish-core/lib/pcie_slots.hpp
@@ -11,6 +11,7 @@
 #include "utils/json_utils.hpp"
 
 #include <boost/system/error_code.hpp>
+#include <boost/url/format.hpp>
 #include <sdbusplus/asio/property.hpp>
 #include <sdbusplus/unpack_properties.hpp>
 
@@ -214,8 +215,8 @@
 
     asyncResp->res.jsonValue["@odata.type"] = "#PCIeSlots.v1_4_1.PCIeSlots";
     asyncResp->res.jsonValue["Name"] = "PCIe Slot Information";
-    asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
-        "redfish", "v1", "Chassis", chassisID, "PCIeSlots");
+    asyncResp->res.jsonValue["@odata.id"] =
+        boost::urls::format("/redfish/v1/Chassis/{}/PCIeSlots", chassisID);
     asyncResp->res.jsonValue["Id"] = "1";
     asyncResp->res.jsonValue["Slots"] = nlohmann::json::array();
 
diff --git a/redfish-core/lib/power_subsystem.hpp b/redfish-core/lib/power_subsystem.hpp
index 52e1ec9..d54fd18 100644
--- a/redfish-core/lib/power_subsystem.hpp
+++ b/redfish-core/lib/power_subsystem.hpp
@@ -6,6 +6,8 @@
 #include "registries/privilege_registry.hpp"
 #include "utils/chassis_utils.hpp"
 
+#include <boost/url/format.hpp>
+
 #include <memory>
 #include <optional>
 #include <string>
@@ -31,13 +33,13 @@
         "#PowerSubsystem.v1_1_0.PowerSubsystem";
     asyncResp->res.jsonValue["Name"] = "Power Subsystem";
     asyncResp->res.jsonValue["Id"] = "PowerSubsystem";
-    asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
-        "redfish", "v1", "Chassis", chassisId, "PowerSubsystem");
+    asyncResp->res.jsonValue["@odata.id"] =
+        boost::urls::format("/redfish/v1/Chassis/{}/PowerSubsystem", chassisId);
     asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
     asyncResp->res.jsonValue["Status"]["Health"] = "OK";
     asyncResp->res.jsonValue["PowerSupplies"]["@odata.id"] =
-        crow::utility::urlFromPieces("redfish", "v1", "Chassis", chassisId,
-                                     "PowerSubsystem", "PowerSupplies");
+        boost::urls::format(
+            "/redfish/v1/Chassis/{}/PowerSubsystem/PowerSupplies", chassisId);
 }
 
 inline void handlePowerSubsystemCollectionHead(
diff --git a/redfish-core/lib/power_supply.hpp b/redfish-core/lib/power_supply.hpp
index 266bda2..430a29a 100644
--- a/redfish-core/lib/power_supply.hpp
+++ b/redfish-core/lib/power_supply.hpp
@@ -6,6 +6,8 @@
 #include "registries/privilege_registry.hpp"
 #include "utils/chassis_utils.hpp"
 
+#include <boost/url/format.hpp>
+
 #include <memory>
 #include <optional>
 #include <string>
@@ -39,9 +41,8 @@
     asyncResp->res.jsonValue["@odata.type"] =
         "#PowerSupplyCollection.PowerSupplyCollection";
     asyncResp->res.jsonValue["Name"] = "Power Supply Collection";
-    asyncResp->res.jsonValue["@odata.id"] =
-        crow::utility::urlFromPieces("redfish", "v1", "Chassis", chassisId,
-                                     "PowerSubsystem", "PowerSupplies");
+    asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
+        "/redfish/v1/Chassis/{}/PowerSubsystem/PowerSupplies", chassisId);
     asyncResp->res.jsonValue["Description"] =
         "The collection of PowerSupply resource instances.";
     asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
diff --git a/redfish-core/lib/processor.hpp b/redfish-core/lib/processor.hpp
index 1223875..19b059a 100644
--- a/redfish-core/lib/processor.hpp
+++ b/redfish-core/lib/processor.hpp
@@ -28,6 +28,7 @@
 
 #include <boost/container/flat_map.hpp>
 #include <boost/system/error_code.hpp>
+#include <boost/url/format.hpp>
 #include <sdbusplus/asio/property.hpp>
 #include <sdbusplus/message/native_types.hpp>
 #include <sdbusplus/unpack_properties.hpp>
@@ -553,9 +554,9 @@
         {
             const std::string& dbusPath = appliedConfig->str;
             nlohmann::json::object_t operatingConfig;
-            operatingConfig["@odata.id"] = crow::utility::urlFromPieces(
-                "redfish", "v1", "Systems", "system", "Processors", cpuId,
-                "OperatingConfigs");
+            operatingConfig["@odata.id"] = boost::urls::format(
+                "/redfish/v1/Systems/system/Processors/{}/OperatingConfigs",
+                cpuId);
             json["OperatingConfigs"] = std::move(operatingConfig);
 
             // Reuse the D-Bus config object name for the Redfish
@@ -571,9 +572,9 @@
                 return;
             }
             nlohmann::json::object_t appliedOperatingConfig;
-            appliedOperatingConfig["@odata.id"] = crow::utility::urlFromPieces(
-                "redfish", "v1", "Systems", "system", "Processors", cpuId,
-                "OperatingConfigs", dbusPath.substr(baseNamePos + 1));
+            appliedOperatingConfig["@odata.id"] = boost::urls::format(
+                "/redfish/v1/Systems/system/Processors/{}/OperatingConfigs/{}",
+                cpuId, dbusPath.substr(baseNamePos + 1));
             json["AppliedOperatingConfig"] = std::move(appliedOperatingConfig);
 
             // Once we found the current applied config, queue another
@@ -1071,9 +1072,9 @@
         }
         asyncResp->res.jsonValue["@odata.type"] =
             "#OperatingConfigCollection.OperatingConfigCollection";
-        asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
-            "redfish", "v1", "Systems", "system", "Processors", cpuName,
-            "OperatingConfigs");
+        asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
+            "/redfish/v1/Systems/system/Processors/{}/OperatingConfigs",
+            cpuName);
         asyncResp->res.jsonValue["Name"] = "Operating Config Collection";
 
         // First find the matching CPU object so we know how to
@@ -1111,9 +1112,9 @@
                 };
                 collection_util::getCollectionMembers(
                     asyncResp,
-                    crow::utility::urlFromPieces("redfish", "v1", "Systems",
-                                                 "system", "Processors",
-                                                 cpuName, "OperatingConfigs"),
+                    boost::urls::format(
+                        "/redfish/v1/Systems/system/Processors/{}/OperatingConfigs",
+                        cpuName),
                     interface, object.c_str());
                 return;
             }
@@ -1162,9 +1163,9 @@
 
                 nlohmann::json& json = asyncResp->res.jsonValue;
                 json["@odata.type"] = "#OperatingConfig.v1_0_0.OperatingConfig";
-                json["@odata.id"] = crow::utility::urlFromPieces(
-                    "redfish", "v1", "Systems", "system", "Processors", cpuName,
-                    "OperatingConfigs", configName);
+                json["@odata.id"] = boost::urls::format(
+                    "/redfish/v1/Systems/system/Processors/{}/OperatingConfigs/{}",
+                    cpuName, configName);
                 json["Name"] = "Processor Profile";
                 json["Id"] = configName;
 
@@ -1260,8 +1261,8 @@
             "</redfish/v1/JsonSchemas/Processor/Processor.json>; rel=describedby");
         asyncResp->res.jsonValue["@odata.type"] =
             "#Processor.v1_11_0.Processor";
-        asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
-            "redfish", "v1", "Systems", "system", "Processors", processorId);
+        asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
+            "/redfish/v1/Systems/system/Processors/{}", processorId);
 
         getProcessorObject(
             asyncResp, processorId,
diff --git a/redfish-core/lib/redfish_sessions.hpp b/redfish-core/lib/redfish_sessions.hpp
index 9fc0832..065878e 100644
--- a/redfish-core/lib/redfish_sessions.hpp
+++ b/redfish-core/lib/redfish_sessions.hpp
@@ -23,6 +23,8 @@
 #include "registries/privilege_registry.hpp"
 #include "utils/json_utils.hpp"
 
+#include <boost/url/format.hpp>
+
 namespace redfish
 {
 
@@ -31,8 +33,8 @@
 {
     res.jsonValue["Id"] = session.uniqueId;
     res.jsonValue["UserName"] = session.username;
-    res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
-        "redfish", "v1", "SessionService", "Sessions", session.uniqueId);
+    res.jsonValue["@odata.id"] = boost::urls::format(
+        "/redfish/v1/SessionService/Sessions/{}", session.uniqueId);
     res.jsonValue["@odata.type"] = "#Session.v1_5_0.Session";
     res.jsonValue["Name"] = "User Session";
     res.jsonValue["Description"] = "Manager User Session";
@@ -126,8 +128,8 @@
     for (const std::string* uid : sessionIds)
     {
         nlohmann::json::object_t session;
-        session["@odata.id"] = crow::utility::urlFromPieces(
-            "redfish", "v1", "SessionService", "Sessions", *uid);
+        session["@odata.id"] =
+            boost::urls::format("/redfish/v1/SessionService/Sessions/{}", *uid);
         ret.emplace_back(std::move(session));
     }
     return ret;
@@ -234,8 +236,8 @@
     {
         messages::passwordChangeRequired(
             asyncResp->res,
-            crow::utility::urlFromPieces("redfish", "v1", "AccountService",
-                                         "Accounts", session->username));
+            boost::urls::format("/redfish/v1/AccountService/Accounts/{}",
+                                session->username));
     }
 
     fillSessionObject(asyncResp->res, *session);
diff --git a/redfish-core/lib/redfish_v1.hpp b/redfish-core/lib/redfish_v1.hpp
index b3174fb..b7a1f4c 100644
--- a/redfish-core/lib/redfish_v1.hpp
+++ b/redfish-core/lib/redfish_v1.hpp
@@ -9,6 +9,8 @@
 #include "schemas.hpp"
 #include "utility.hpp"
 
+#include <boost/url/format.hpp>
+
 #include <string>
 
 namespace redfish
@@ -86,8 +88,8 @@
     for (std::string_view schema : schemas)
     {
         nlohmann::json::object_t member;
-        member["@odata.id"] = crow::utility::urlFromPieces(
-            "redfish", "v1", "JsonSchemas", schema);
+        member["@odata.id"] = boost::urls::format("/redfish/v1/JsonSchemas/{}",
+                                                  schema);
         members.emplace_back(std::move(member));
     }
     json["Members"] = std::move(members);
@@ -110,8 +112,8 @@
     }
 
     nlohmann::json& json = asyncResp->res.jsonValue;
-    json["@odata.id"] = crow::utility::urlFromPieces("redfish", "v1",
-                                                     "JsonSchemas", schema);
+    json["@odata.id"] = boost::urls::format("/redfish/v1/JsonSchemas/{}",
+                                            schema);
     json["@odata.type"] = "#JsonSchemaFile.v1_0_2.JsonSchemaFile";
     json["Name"] = schema + " Schema File";
     json["Description"] = schema + " Schema File Location";
@@ -130,8 +132,8 @@
     locationEntry["Language"] = "en";
     locationEntry["PublicationUri"] = "http://redfish.dmtf.org/schemas/v1/" +
                                       schema + ".json";
-    locationEntry["Uri"] = crow::utility::urlFromPieces(
-        "redfish", "v1", "JsonSchemas", schema, std::string(schema) + ".json");
+    locationEntry["Uri"] = boost::urls::format(
+        "/redfish/v1/JsonSchemas/{}/{}", schema, std::string(schema) + ".json");
 
     locationArray.emplace_back(locationEntry);
 
diff --git a/redfish-core/lib/roles.hpp b/redfish-core/lib/roles.hpp
index a3382e8..784f716 100644
--- a/redfish-core/lib/roles.hpp
+++ b/redfish-core/lib/roles.hpp
@@ -20,6 +20,7 @@
 #include "query.hpp"
 #include "registries/privilege_registry.hpp"
 
+#include <boost/url/format.hpp>
 #include <sdbusplus/asio/property.hpp>
 
 #include <variant>
@@ -93,8 +94,8 @@
         asyncResp->res.jsonValue["IsPredefined"] = true;
         asyncResp->res.jsonValue["Id"] = roleId;
         asyncResp->res.jsonValue["RoleId"] = roleId;
-        asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
-            "redfish", "v1", "AccountService", "Roles", roleId);
+        asyncResp->res.jsonValue["@odata.id"] =
+            boost::urls::format("/redfish/v1/AccountService/Roles/{}", roleId);
         asyncResp->res.jsonValue["AssignedPrivileges"] = std::move(privArray);
         });
 }
@@ -137,8 +138,8 @@
                 if (!role.empty())
                 {
                     nlohmann::json::object_t member;
-                    member["@odata.id"] = crow::utility::urlFromPieces(
-                        "redfish", "v1", "AccountService", "Roles", role);
+                    member["@odata.id"] = boost::urls::format(
+                        "/redfish/v1/AccountService/Roles/{}", role);
                     memberArray.emplace_back(std::move(member));
                 }
             }
diff --git a/redfish-core/lib/sensors.hpp b/redfish-core/lib/sensors.hpp
index 93e8196..59c954b 100644
--- a/redfish-core/lib/sensors.hpp
+++ b/redfish-core/lib/sensors.hpp
@@ -32,6 +32,7 @@
 #include <boost/algorithm/string/replace.hpp>
 #include <boost/range/algorithm/replace_copy_if.hpp>
 #include <boost/system/error_code.hpp>
+#include <boost/url/format.hpp>
 #include <sdbusplus/asio/property.hpp>
 #include <sdbusplus/unpack_properties.hpp>
 
@@ -559,8 +560,8 @@
         }
         populateChassisNode(asyncResp->res.jsonValue, chassisSubNode);
 
-        asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
-            "redfish", "v1", "Chassis", chassisIdStr, chassisSubNode);
+        asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
+            "/redfish/v1/Chassis/{}/{}", chassisIdStr, chassisSubNode);
 
         // Get the list of all sensors for this Chassis element
         std::string sensorPath = *chassisPath + "/all_sensors";
@@ -1120,9 +1121,10 @@
                                                 .jsonValue["Redundancy"];
 
                     nlohmann::json::object_t redundancy;
-                    boost::urls::url url = crow::utility::urlFromPieces(
-                        "redfish", "v1", "Chassis", sensorsAsyncResp->chassisId,
-                        sensorsAsyncResp->chassisSubNode);
+                    boost::urls::url url =
+                        boost::urls::format("/redfish/v1/Chassis/{}/{}",
+                                            sensorsAsyncResp->chassisId,
+                                            sensorsAsyncResp->chassisSubNode);
                     url.set_fragment(("/Redundancy"_json_pointer / jResp.size())
                                          .to_string());
                     redundancy["@odata.id"] = std::move(url);
@@ -2194,8 +2196,8 @@
     // Add new PowerSupply object to JSON array
     powerSupplyArray.push_back({});
     nlohmann::json& powerSupply = powerSupplyArray.back();
-    boost::urls::url url = crow::utility::urlFromPieces(
-        "redfish", "v1", "Chassis", chassisId, "Power");
+    boost::urls::url url = boost::urls::format("/redfish/v1/Chassis/{}/Power",
+                                               chassisId);
     url.set_fragment(("/PowerSupplies"_json_pointer).to_string());
     powerSupply["@odata.id"] = std::move(url);
     powerSupply["Name"] = boost::replace_all_copy(inventoryItem.name, "_", " ");
@@ -2319,10 +2321,10 @@
                     sensorId += sensorName;
 
                     sensorsAsyncResp->asyncResp->res.jsonValue["@odata.id"] =
-                        crow::utility::urlFromPieces(
-                            "redfish", "v1", "Chassis",
-                            sensorsAsyncResp->chassisId,
-                            sensorsAsyncResp->chassisSubNode, sensorId);
+                        boost::urls::format("/redfish/v1/Chassis/{}/{}/{}",
+                                            sensorsAsyncResp->chassisId,
+                                            sensorsAsyncResp->chassisSubNode,
+                                            sensorId);
                     sensorJson = &(sensorsAsyncResp->asyncResp->res.jsonValue);
                 }
                 else
@@ -2379,8 +2381,8 @@
                             // PowerControl. Follows MemberId naming and
                             // naming in power.hpp.
                             nlohmann::json::object_t power;
-                            boost::urls::url url = crow::utility::urlFromPieces(
-                                "redfish", "v1", "Chassis",
+                            boost::urls::url url = boost::urls::format(
+                                "/redfish/v1/Chassis/{}/{}",
                                 sensorsAsyncResp->chassisId,
                                 sensorsAsyncResp->chassisSubNode);
                             url.set_fragment((""_json_pointer / fieldName / "0")
@@ -2411,8 +2413,8 @@
                         sensorId += sensorName;
 
                         nlohmann::json::object_t member;
-                        member["@odata.id"] = crow::utility::urlFromPieces(
-                            "redfish", "v1", "Chassis",
+                        member["@odata.id"] = boost::urls::format(
+                            "/redfish/v1/Chassis/{}/{}/{}",
                             sensorsAsyncResp->chassisId,
                             sensorsAsyncResp->chassisSubNode, sensorId);
                         tempArray.emplace_back(std::move(member));
@@ -2421,8 +2423,8 @@
                     else
                     {
                         nlohmann::json::object_t member;
-                        boost::urls::url url = crow::utility::urlFromPieces(
-                            "redfish", "v1", "Chassis",
+                        boost::urls::url url = boost::urls::format(
+                            "/redfish/v1/Chassis/{}/{}",
                             sensorsAsyncResp->chassisId,
                             sensorsAsyncResp->chassisSubNode);
                         url.set_fragment(
@@ -2793,8 +2795,8 @@
         std::string id = type;
         id += "_";
         id += sensorName;
-        member["@odata.id"] = crow::utility::urlFromPieces(
-            "redfish", "v1", "Chassis", chassisId, chassisSubNode, id);
+        member["@odata.id"] = boost::urls::format(
+            "/redfish/v1/Chassis/{}/{}/{}", chassisId, chassisSubNode, id);
 
         entriesArray.emplace_back(std::move(member));
     }
@@ -2890,8 +2892,8 @@
         return;
     }
 
-    asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
-        "redfish", "v1", "Chassis", chassisId, "Sensors", sensorId);
+    asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
+        "/redfish/v1/Chassis/{}/Sensors/{}", chassisId, sensorId);
 
     BMCWEB_LOG_DEBUG << "Sensor doGet enter";
 
diff --git a/redfish-core/lib/storage.hpp b/redfish-core/lib/storage.hpp
index 63f96b6..fe4842c 100644
--- a/redfish-core/lib/storage.hpp
+++ b/redfish-core/lib/storage.hpp
@@ -26,6 +26,7 @@
 #include "utils/dbus_utils.hpp"
 
 #include <boost/system/error_code.hpp>
+#include <boost/url/format.hpp>
 #include <sdbusplus/asio/property.hpp>
 #include <sdbusplus/unpack_properties.hpp>
 
@@ -102,8 +103,8 @@
             }
 
             nlohmann::json::object_t driveJson;
-            driveJson["@odata.id"] = crow::utility::urlFromPieces(
-                "redfish", "v1", "Systems", "system", "Storage", "1", "Drives",
+            driveJson["@odata.id"] = boost::urls::format(
+                "/redfish/v1/Systems/system/Storage/1/Drives/{}",
                 object.filename());
             driveArray.emplace_back(std::move(driveJson));
         }
@@ -157,11 +158,9 @@
 
             storageController["@odata.type"] =
                 "#Storage.v1_7_0.StorageController";
-            storageController["@odata.id"] =
-                crow::utility::urlFromPieces("redfish", "v1", "Systems",
-                                             "system", "Storage", "1")
-                    .set_fragment(("/StorageControllers"_json_pointer / index)
-                                      .to_string());
+            storageController["@odata.id"] = boost::urls::format(
+                "/redfish/v1/Systems/system/Storage/1#{}",
+                ("/StorageControllers"_json_pointer / index).to_string());
             storageController["Name"] = id;
             storageController["MemberId"] = id;
             storageController["Status"]["State"] = "Enabled";
@@ -608,10 +607,8 @@
                 drive->second;
 
             asyncResp->res.jsonValue["@odata.type"] = "#Drive.v1_7_0.Drive";
-            asyncResp->res.jsonValue["@odata.id"] =
-                crow::utility::urlFromPieces("redfish", "v1", "Systems",
-                                             "system", "Storage", "1", "Drives",
-                                             driveId);
+            asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
+                "/redfish/v1/Systems/system/Storage/1/Drives/{}", driveId);
             asyncResp->res.jsonValue["Name"] = driveId;
             asyncResp->res.jsonValue["Id"] = driveId;
 
@@ -624,11 +621,11 @@
             }
 
             getMainChassisId(
-                asyncResp, [](const std::string& chassisId,
-                              const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
-                    aRsp->res.jsonValue["Links"]["Chassis"]["@odata.id"] =
-                        crow::utility::urlFromPieces("redfish", "v1", "Chassis",
-                                                     chassisId);
+                asyncResp,
+                [](const std::string& chassisId,
+                   const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
+                aRsp->res.jsonValue["Links"]["Chassis"]["@odata.id"] =
+                    boost::urls::format("/redfish/v1/Chassis/{}", chassisId);
                 });
 
             // default it to Enabled
@@ -697,8 +694,7 @@
             asyncResp->res.jsonValue["@odata.type"] =
                 "#DriveCollection.DriveCollection";
             asyncResp->res.jsonValue["@odata.id"] =
-                crow::utility::urlFromPieces("redfish", "v1", "Chassis",
-                                             chassisId, "Drives");
+                boost::urls::format("/redfish/v1/Chassis/{}/Drives", chassisId);
             asyncResp->res.jsonValue["Name"] = "Drive Collection";
 
             // Association lambda
@@ -728,9 +724,9 @@
                 for (const auto& leafName : leafNames)
                 {
                     nlohmann::json::object_t member;
-                    member["@odata.id"] = crow::utility::urlFromPieces(
-                        "redfish", "v1", "Chassis", chassisId, "Drives",
-                        leafName);
+                    member["@odata.id"] =
+                        boost::urls::format("/redfish/v1/Chassis/{}/Drives/{}",
+                                            chassisId, leafName);
                     members.emplace_back(std::move(member));
                     // navigation links will be registered in next patch set
                 }
@@ -777,8 +773,8 @@
             continue;
         }
 
-        asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
-            "redfish", "v1", "Chassis", chassisId, "Drives", driveName);
+        asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
+            "/redfish/v1/Chassis/{}/Drives/{}", chassisId, driveName);
 
         asyncResp->res.jsonValue["@odata.type"] = "#Drive.v1_7_0.Drive";
         asyncResp->res.jsonValue["Name"] = driveName;
@@ -788,7 +784,7 @@
 
         nlohmann::json::object_t linkChassisNav;
         linkChassisNav["@odata.id"] =
-            crow::utility::urlFromPieces("redfish", "v1", "Chassis", chassisId);
+            boost::urls::format("/redfish/v1/Chassis/{}", chassisId);
         asyncResp->res.jsonValue["Links"]["Chassis"] = linkChassisNav;
 
         addAllDriveInfo(asyncResp, connectionNames[0].first, path,
diff --git a/redfish-core/lib/systems.hpp b/redfish-core/lib/systems.hpp
index c474d08..f9938c7 100644
--- a/redfish-core/lib/systems.hpp
+++ b/redfish-core/lib/systems.hpp
@@ -32,6 +32,7 @@
 
 #include <boost/container/flat_map.hpp>
 #include <boost/system/error_code.hpp>
+#include <boost/url/format.hpp>
 #include <sdbusplus/asio/property.hpp>
 #include <sdbusplus/unpack_properties.hpp>
 
@@ -3118,8 +3119,8 @@
                             const std::shared_ptr<bmcweb::AsyncResp>& aRsp) {
             nlohmann::json::array_t chassisArray;
             nlohmann::json& chassis = chassisArray.emplace_back();
-            chassis["@odata.id"] = crow::utility::urlFromPieces(
-                "redfish", "v1", "Chassis", chassisId);
+            chassis["@odata.id"] = boost::urls::format("/redfish/v1/Chassis/{}",
+                                                       chassisId);
             aRsp->res.jsonValue["Links"]["Chassis"] = std::move(chassisArray);
         });
 
diff --git a/redfish-core/lib/task.hpp b/redfish-core/lib/task.hpp
index 167a0c7..e0058f5 100644
--- a/redfish-core/lib/task.hpp
+++ b/redfish-core/lib/task.hpp
@@ -26,6 +26,7 @@
 
 #include <boost/asio/post.hpp>
 #include <boost/asio/steady_timer.hpp>
+#include <boost/url/format.hpp>
 #include <sdbusplus/bus/match.hpp>
 
 #include <chrono>
@@ -409,8 +410,8 @@
         }
         asyncResp->res.jsonValue["TaskStatus"] = ptr->status;
         asyncResp->res.jsonValue["Messages"] = ptr->messages;
-        asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
-            "redfish", "v1", "TaskService", "Tasks", strParam);
+        asyncResp->res.jsonValue["@odata.id"] =
+            boost::urls::format("/redfish/v1/TaskService/Tasks/{}", strParam);
         if (!ptr->gave204)
         {
             asyncResp->res.jsonValue["TaskMonitor"] =
@@ -456,9 +457,9 @@
                 continue; // shouldn't be possible
             }
             nlohmann::json::object_t member;
-            member["@odata.id"] = crow::utility::urlFromPieces(
-                "redfish", "v1", "TaskService", "Tasks",
-                std::to_string(task->index));
+            member["@odata.id"] =
+                boost::urls::format("/redfish/v1/TaskService/Tasks/{}",
+                                    std::to_string(task->index));
             members.emplace_back(std::move(member));
         }
         });
diff --git a/redfish-core/lib/thermal_subsystem.hpp b/redfish-core/lib/thermal_subsystem.hpp
index 271951e..6528a55 100644
--- a/redfish-core/lib/thermal_subsystem.hpp
+++ b/redfish-core/lib/thermal_subsystem.hpp
@@ -7,6 +7,8 @@
 #include "utils/chassis_utils.hpp"
 #include "utils/json_utils.hpp"
 
+#include <boost/url/format.hpp>
+
 #include <optional>
 #include <string>
 
@@ -33,8 +35,8 @@
     asyncResp->res.jsonValue["Name"] = "Thermal Subsystem";
     asyncResp->res.jsonValue["Id"] = "ThermalSubsystem";
 
-    asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
-        "redfish", "v1", "Chassis", chassisId, "ThermalSubsystem");
+    asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
+        "/redfish/v1/Chassis/{}/ThermalSubsystem", chassisId);
 
     asyncResp->res.jsonValue["Status"]["State"] = "Enabled";
     asyncResp->res.jsonValue["Status"]["Health"] = "OK";
diff --git a/redfish-core/lib/trigger.hpp b/redfish-core/lib/trigger.hpp
index 5fe9678..68d6dd2 100644
--- a/redfish-core/lib/trigger.hpp
+++ b/redfish-core/lib/trigger.hpp
@@ -8,6 +8,7 @@
 #include "utils/telemetry_utils.hpp"
 #include "utils/time_utils.hpp"
 
+#include <boost/url/format.hpp>
 #include <sdbusplus/asio/property.hpp>
 #include <sdbusplus/unpack_properties.hpp>
 
@@ -161,9 +162,9 @@
         }
 
         nlohmann::json::object_t report;
-        report["@odata.id"] =
-            crow::utility::urlFromPieces("redfish", "v1", "TelemetryService",
-                                         "MetricReportDefinitions", reportId);
+        report["@odata.id"] = boost::urls::format(
+            "/redfish/v1/TelemetryService/MetricReportDefinitions/{}",
+            reportId);
         reports.emplace_back(std::move(report));
     }
 
@@ -282,8 +283,8 @@
     }
 
     json["@odata.type"] = "#Triggers.v1_2_0.Triggers";
-    json["@odata.id"] = crow::utility::urlFromPieces(
-        "redfish", "v1", "TelemetryService", "Triggers", id);
+    json["@odata.id"] =
+        boost::urls::format("/redfish/v1/TelemetryService/Triggers/{}", id);
     json["Id"] = id;
 
     return true;
diff --git a/redfish-core/lib/update_service.hpp b/redfish-core/lib/update_service.hpp
index b6c0487..5f46d0a 100644
--- a/redfish-core/lib/update_service.hpp
+++ b/redfish-core/lib/update_service.hpp
@@ -28,6 +28,7 @@
 
 #include <boost/algorithm/string/case_conv.hpp>
 #include <boost/system/error_code.hpp>
+#include <boost/url/format.hpp>
 #include <sdbusplus/asio/property.hpp>
 #include <sdbusplus/bus/match.hpp>
 #include <sdbusplus/unpack_properties.hpp>
@@ -905,9 +906,8 @@
 
                 nlohmann::json& members = asyncResp->res.jsonValue["Members"];
                 nlohmann::json::object_t member;
-                member["@odata.id"] = crow::utility::urlFromPieces(
-                    "redfish", "v1", "UpdateService", "FirmwareInventory",
-                    swId);
+                member["@odata.id"] = boost::urls::format(
+                    "/redfish/v1/UpdateService/FirmwareInventory/{}", swId);
                 members.emplace_back(std::move(member));
                 asyncResp->res.jsonValue["Members@odata.count"] =
                     members.size();
@@ -1029,8 +1029,8 @@
         std::shared_ptr<std::string> swId =
             std::make_shared<std::string>(param);
 
-        asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
-            "redfish", "v1", "UpdateService", "FirmwareInventory", *swId);
+        asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
+            "/redfish/v1/UpdateService/FirmwareInventory/{}", *swId);
 
         constexpr std::array<std::string_view, 1> interfaces = {
             "xyz.openbmc_project.Software.Version"};
@@ -1072,9 +1072,10 @@
             {
                 BMCWEB_LOG_ERROR << "Input swID " << *swId << " not found!";
                 messages::resourceMissingAtURI(
-                    asyncResp->res, crow::utility::urlFromPieces(
-                                        "redfish", "v1", "UpdateService",
-                                        "FirmwareInventory", *swId));
+                    asyncResp->res,
+                    boost::urls::format(
+                        "/redfish/v1/UpdateService/FirmwareInventory/{}",
+                        *swId));
                 return;
             }
             asyncResp->res.jsonValue["@odata.type"] =
diff --git a/redfish-core/lib/virtual_media.hpp b/redfish-core/lib/virtual_media.hpp
index 373881e..8192da2 100644
--- a/redfish-core/lib/virtual_media.hpp
+++ b/redfish-core/lib/virtual_media.hpp
@@ -25,6 +25,7 @@
 #include "utils/json_utils.hpp"
 
 #include <boost/process/async_pipe.hpp>
+#include <boost/url/format.hpp>
 #include <boost/url/url_view.hpp>
 
 #include <array>
@@ -245,8 +246,8 @@
                                      const std::string& resName)
 {
     nlohmann::json item;
-    item["@odata.id"] = crow::utility::urlFromPieces(
-        "redfish", "v1", "Managers", name, "VirtualMedia", resName);
+    item["@odata.id"] = boost::urls::format(
+        "/redfish/v1/Managers/{}/VirtualMedia/{}", name, resName);
 
     item["@odata.type"] = "#VirtualMedia.v1_3_0.VirtualMedia";
     item["Name"] = "Virtual Removable Media";
@@ -290,8 +291,8 @@
                 continue;
             }
 
-            item["@odata.id"] = crow::utility::urlFromPieces(
-                "redfish", "v1", "Managers", name, "VirtualMedia", path);
+            item["@odata.id"] = boost::urls::format(
+                "/redfish/v1/Managers/{}/VirtualMedia/{}", name, path);
             members.emplace_back(std::move(item));
         }
         aResp->res.jsonValue["Members@odata.count"] = members.size();
@@ -318,19 +319,18 @@
     // Check if dbus path is Legacy type
     if (mode == VmMode::Legacy)
     {
-        asyncResp->res
-            .jsonValue["Actions"]["#VirtualMedia.InsertMedia"]["target"] =
-            crow::utility::urlFromPieces("redfish", "v1", "Managers", name,
-                                         "VirtualMedia", resName, "Actions",
-                                         "VirtualMedia.InsertMedia");
+        asyncResp->res.jsonValue["Actions"]["#VirtualMedia.InsertMedia"]
+                                ["target"] = boost::urls::format(
+            "/redfish/v1/Managers/{}/VirtualMedia/{}/Actions/VirtualMedia.InsertMedia",
+            name, resName);
     }
 
     vmParseInterfaceObject(item.second, asyncResp);
 
-    asyncResp->res.jsonValue["Actions"]["#VirtualMedia.EjectMedia"]["target"] =
-        crow::utility::urlFromPieces("redfish", "v1", "Managers", name,
-                                     "VirtualMedia", resName, "Actions",
-                                     "VirtualMedia.EjectMedia");
+    asyncResp->res.jsonValue["Actions"]["#VirtualMedia.EjectMedia"]
+                            ["target"] = boost::urls::format(
+        "/redfish/v1/Managers/{}/VirtualMedia/{}/Actions/VirtualMedia.EjectMedia",
+        name, resName);
 }
 
 /**
@@ -986,8 +986,8 @@
     asyncResp->res.jsonValue["@odata.type"] =
         "#VirtualMediaCollection.VirtualMediaCollection";
     asyncResp->res.jsonValue["Name"] = "Virtual Media Services";
-    asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
-        "redfish", "v1", "Managers", name, "VirtualMedia");
+    asyncResp->res.jsonValue["@odata.id"] =
+        boost::urls::format("/redfish/v1/Managers/{}/VirtualMedia", name);
 
     dbus::utility::getDbusObject(
         "/xyz/openbmc_project/VirtualMedia", {},