Move Redfish PECI to the new json interface

This change adds vector handling to the new json interface
and modifies the SendRawPECI Redfish command to utilize it.

Tested: Executed raw PECI commands with good and bad input
to check that it will work and error out correctly.

Change-Id: Ic1c837f5823d28555f727849156b4dabf1b8acef
Signed-off-by: Ed Tanous <ed.tanous@intel.com>
Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
diff --git a/redfish-core/include/utils/json_utils.hpp b/redfish-core/include/utils/json_utils.hpp
index 778a905..1d969e0 100644
--- a/redfish-core/include/utils/json_utils.hpp
+++ b/redfish-core/include/utils/json_utils.hpp
@@ -55,6 +55,16 @@
 template <typename Type>
 constexpr bool is_optional_v = is_optional<Type>::value;
 
+template <typename Type> struct is_vector : std::false_type
+{
+};
+
+template <typename Type> struct is_vector<std::vector<Type>> : std::true_type
+{
+};
+
+template <typename Type> constexpr bool is_vector_v = is_vector<Type>::value;
+
 template <typename Type>
 void unpackValue(nlohmann::json& jsonValue, const std::string& key,
                  crow::Response& res, Type& value)
@@ -94,6 +104,21 @@
         value.emplace();
         unpackValue<typename Type::value_type>(jsonValue, key, res, *value);
     }
+    else if constexpr (is_vector_v<Type>)
+    {
+        if (!jsonValue.is_array())
+        {
+            messages::propertyValueTypeError(res, res.jsonValue.dump(), key);
+            return;
+        }
+
+        for (const auto& val : jsonValue.items())
+        {
+            value.emplace_back();
+            unpackValue<typename Type::value_type>(val.value(), key, res,
+                                                   value.back());
+        }
+    }
     else
     {
         using JsonType = std::add_const_t<std::add_pointer_t<Type>>;
diff --git a/redfish-core/lib/log_services.hpp b/redfish-core/lib/log_services.hpp
index a0c7351..2dda752 100644
--- a/redfish-core/lib/log_services.hpp
+++ b/redfish-core/lib/log_services.hpp
@@ -1312,62 +1312,16 @@
                 const std::vector<std::string> &params) override
     {
         std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
-        // Get the Raw PECI command from the request
-        nlohmann::json rawPECICmd;
-        if (!json_util::processJsonFromRequest(res, req, rawPECICmd))
-        {
-            return;
-        }
-        // Get the Client Address from the request
-        nlohmann::json::const_iterator caIt = rawPECICmd.find("ClientAddress");
-        if (caIt == rawPECICmd.end())
-        {
-            messages::propertyMissing(asyncResp->res, "ClientAddress");
-            return;
-        }
-        const uint64_t *ca = caIt->get_ptr<const uint64_t *>();
-        if (ca == nullptr)
-        {
-            messages::propertyValueTypeError(asyncResp->res, caIt->dump(),
-                                             "ClientAddress");
-            return;
-        }
-        // Get the Read Length from the request
-        const uint8_t clientAddress = static_cast<uint8_t>(*ca);
-        nlohmann::json::const_iterator rlIt = rawPECICmd.find("ReadLength");
-        if (rlIt == rawPECICmd.end())
-        {
-            messages::propertyMissing(asyncResp->res, "ReadLength");
-            return;
-        }
-        const uint64_t *rl = rlIt->get_ptr<const uint64_t *>();
-        if (rl == nullptr)
-        {
-            messages::propertyValueTypeError(asyncResp->res, rlIt->dump(),
-                                             "ReadLength");
-            return;
-        }
-        // Get the PECI Command from the request
-        const uint32_t readLength = static_cast<uint32_t>(*rl);
-        nlohmann::json::const_iterator pcIt = rawPECICmd.find("PECICommand");
-        if (pcIt == rawPECICmd.end())
-        {
-            messages::propertyMissing(asyncResp->res, "PECICommand");
-            return;
-        }
+        uint8_t clientAddress = 0;
+        uint8_t readLength = 0;
         std::vector<uint8_t> peciCommand;
-        for (auto pc : *pcIt)
+        if (!json_util::readJson(req, res, "ClientAddress", clientAddress,
+                                 "ReadLength", readLength, "PECICommand",
+                                 peciCommand))
         {
-            const uint64_t *val = pc.get_ptr<const uint64_t *>();
-            if (val == nullptr)
-            {
-                messages::propertyValueTypeError(
-                    asyncResp->res, pc.dump(),
-                    "PECICommand/" + std::to_string(peciCommand.size()));
-                return;
-            }
-            peciCommand.push_back(static_cast<uint8_t>(*val));
+            return;
         }
+
         // Callback to return the Raw PECI response
         auto sendRawPECICallback =
             [asyncResp](const boost::system::error_code ec,