summaryrefslogtreecommitdiff
path: root/redfish-core
diff options
context:
space:
mode:
authorAppaRao Puli <apparao.puli@linux.intel.com>2020-05-19 21:43:22 +0300
committerAppaRao Puli <apparao.puli@linux.intel.com>2020-05-29 21:26:14 +0300
commit471a5eb867c6a3e625bc5745edac8e56ad2e549c (patch)
treeeded03aaa8f070b4d73d35da210418b0e554dd11 /redfish-core
parent2056b6d167a3ecb3c1615d906624a91259dc6c1f (diff)
downloadbmcweb-471a5eb867c6a3e625bc5745edac8e56ad2e549c.tar.xz
Update json helper function - readJson
The json helper functions are currently coupled with response(crow::response) and limiting it to use only while sending response. There are some use cases where we don't send crow::response instead we extract json data from files and load configuration. Decoupled the business logic for validating json key existence, json value type checking and range validation with top level use cases. So this json helper functions can be used for validating json and extracting value from json object during init cases also(Ex: Used in EventService config initialization) Added new API in helper function which checks key existence, value is of desired Type and value is in acceptable range and assign value in output parameter. Tested: Verified post and patch methods with different kinds of value types( int, bool, string, vector array, json etc..) and it works. Change-Id: I21a6f9a12aef09f6ca79a02bc01d96efeeb3a20a Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
Diffstat (limited to 'redfish-core')
-rw-r--r--redfish-core/include/utils/json_utils.hpp168
1 files changed, 131 insertions, 37 deletions
diff --git a/redfish-core/include/utils/json_utils.hpp b/redfish-core/include/utils/json_utils.hpp
index 86bd97c5ba..de732ce74a 100644
--- a/redfish-core/include/utils/json_utils.hpp
+++ b/redfish-core/include/utils/json_utils.hpp
@@ -78,22 +78,27 @@ struct is_std_array<std::array<Type, size>> : std::true_type
template <typename Type>
constexpr bool is_std_array_v = is_std_array<Type>::value;
+enum class UnpackErrorCode
+{
+ success,
+ invalidType,
+ outOfRange
+};
+
template <typename ToType, typename FromType>
-bool checkRange(const FromType& from, const std::string& key,
- nlohmann::json& jsonValue, crow::Response& res)
+bool checkRange(const FromType& from, nlohmann::json& jsonValue,
+ const std::string& key)
{
if (from > std::numeric_limits<ToType>::max())
{
BMCWEB_LOG_DEBUG << "Value for key " << key
<< " was greater than max: " << __PRETTY_FUNCTION__;
- messages::propertyValueNotInList(res, jsonValue.dump(), key);
return false;
}
if (from < std::numeric_limits<ToType>::lowest())
{
BMCWEB_LOG_DEBUG << "Value for key " << key
<< " was less than min: " << __PRETTY_FUNCTION__;
- messages::propertyValueNotInList(res, jsonValue.dump(), key);
return false;
}
if constexpr (std::is_floating_point_v<ToType>)
@@ -101,7 +106,6 @@ bool checkRange(const FromType& from, const std::string& key,
if (std::isnan(from))
{
BMCWEB_LOG_DEBUG << "Value for key " << key << " was NAN";
- messages::propertyValueNotInList(res, jsonValue.dump(), key);
return false;
}
}
@@ -110,10 +114,10 @@ bool checkRange(const FromType& from, const std::string& key,
}
template <typename Type>
-bool unpackValue(nlohmann::json& jsonValue, const std::string& key,
- crow::Response& res, Type& value)
+UnpackErrorCode unpackValueWithErrorCode(nlohmann::json& jsonValue,
+ const std::string& key, Type& value)
{
- bool ret = true;
+ UnpackErrorCode ret = UnpackErrorCode::success;
if constexpr (std::is_floating_point_v<Type>)
{
@@ -131,12 +135,11 @@ bool unpackValue(nlohmann::json& jsonValue, const std::string& key,
}
if (jsonPtr == nullptr)
{
- messages::propertyValueTypeError(res, jsonValue.dump(), key);
- return false;
+ return UnpackErrorCode::invalidType;
}
- if (!checkRange<Type>(*jsonPtr, key, jsonValue, res))
+ if (!checkRange<Type>(*jsonPtr, jsonValue, key))
{
- return false;
+ return UnpackErrorCode::outOfRange;
}
value = static_cast<Type>(*jsonPtr);
}
@@ -146,12 +149,11 @@ bool unpackValue(nlohmann::json& jsonValue, const std::string& key,
int64_t* jsonPtr = jsonValue.get_ptr<int64_t*>();
if (jsonPtr == nullptr)
{
- messages::propertyValueTypeError(res, jsonValue.dump(), key);
- return false;
+ return UnpackErrorCode::invalidType;
}
- if (!checkRange<Type>(*jsonPtr, key, jsonValue, res))
+ if (!checkRange<Type>(*jsonPtr, jsonValue, key))
{
- return false;
+ return UnpackErrorCode::outOfRange;
}
value = static_cast<Type>(*jsonPtr);
}
@@ -162,23 +164,15 @@ bool unpackValue(nlohmann::json& jsonValue, const std::string& key,
uint64_t* jsonPtr = jsonValue.get_ptr<uint64_t*>();
if (jsonPtr == nullptr)
{
- messages::propertyValueTypeError(res, jsonValue.dump(), key);
- return false;
+ return UnpackErrorCode::invalidType;
}
- if (!checkRange<Type>(*jsonPtr, key, jsonValue, res))
+ if (!checkRange<Type>(*jsonPtr, jsonValue, key))
{
- return false;
+ return UnpackErrorCode::outOfRange;
}
value = static_cast<Type>(*jsonPtr);
}
- else if constexpr (is_optional_v<Type>)
- {
- value.emplace();
- ret = unpackValue<typename Type::value_type>(jsonValue, key, res,
- *value) &&
- ret;
- }
else if constexpr (std::is_same_v<nlohmann::json, Type>)
{
// Must be a complex type. Simple types (int string etc) should be
@@ -186,12 +180,40 @@ bool unpackValue(nlohmann::json& jsonValue, const std::string& key,
if (!jsonValue.is_object() && !jsonValue.is_array() &&
!jsonValue.is_null())
{
- messages::propertyValueTypeError(res, jsonValue.dump(), key);
- return false;
+ return UnpackErrorCode::invalidType;
}
value = std::move(jsonValue);
}
+ else
+ {
+ using JsonType = std::add_const_t<std::add_pointer_t<Type>>;
+ JsonType jsonPtr = jsonValue.get_ptr<JsonType>();
+ if (jsonPtr == nullptr)
+ {
+ BMCWEB_LOG_DEBUG
+ << "Value for key " << key
+ << " was incorrect type: " << jsonValue.type_name();
+ return UnpackErrorCode::invalidType;
+ }
+ value = std::move(*jsonPtr);
+ }
+ return ret;
+}
+
+template <typename Type>
+bool unpackValue(nlohmann::json& jsonValue, const std::string& key,
+ crow::Response& res, Type& value)
+{
+ bool ret = true;
+
+ if constexpr (is_optional_v<Type>)
+ {
+ value.emplace();
+ ret = unpackValue<typename Type::value_type>(jsonValue, key, res,
+ *value) &&
+ ret;
+ }
else if constexpr (is_std_array_v<Type>)
{
if (!jsonValue.is_array())
@@ -230,18 +252,76 @@ bool unpackValue(nlohmann::json& jsonValue, const std::string& key,
}
else
{
- using JsonType = std::add_const_t<std::add_pointer_t<Type>>;
- JsonType jsonPtr = jsonValue.get_ptr<JsonType>();
- if (jsonPtr == nullptr)
+ UnpackErrorCode ec = unpackValueWithErrorCode(jsonValue, key, value);
+ if (ec != UnpackErrorCode::success)
{
- BMCWEB_LOG_DEBUG
- << "Value for key " << key
- << " was incorrect type: " << jsonValue.type_name();
- messages::propertyValueTypeError(res, jsonValue.dump(), key);
+ if (ec == UnpackErrorCode::invalidType)
+ {
+ messages::propertyValueTypeError(res, jsonValue.dump(), key);
+ }
+ else if (ec == UnpackErrorCode::outOfRange)
+ {
+ messages::propertyValueNotInList(res, jsonValue.dump(), key);
+ }
return false;
}
- value = std::move(*jsonPtr);
}
+
+ return ret;
+}
+
+template <typename Type>
+bool unpackValue(nlohmann::json& jsonValue, const std::string& key, Type& value)
+{
+ bool ret = true;
+ if constexpr (is_optional_v<Type>)
+ {
+ value.emplace();
+ ret = unpackValue<typename Type::value_type>(jsonValue, key, *value) &&
+ ret;
+ }
+ else if constexpr (is_std_array_v<Type>)
+ {
+ if (!jsonValue.is_array())
+ {
+ return false;
+ }
+ if (jsonValue.size() != value.size())
+ {
+ return false;
+ }
+ size_t index = 0;
+ for (const auto& val : jsonValue.items())
+ {
+ ret = unpackValue<typename Type::value_type>(val.value(), key,
+ value[index++]) &&
+ ret;
+ }
+ }
+ else if constexpr (is_vector_v<Type>)
+ {
+ if (!jsonValue.is_array())
+ {
+ return false;
+ }
+
+ for (const auto& val : jsonValue.items())
+ {
+ value.emplace_back();
+ ret = unpackValue<typename Type::value_type>(val.value(), key,
+ value.back()) &&
+ ret;
+ }
+ }
+ else
+ {
+ UnpackErrorCode ec = unpackValueWithErrorCode(jsonValue, key, value);
+ if (ec != UnpackErrorCode::success)
+ {
+ return false;
+ }
+ }
+
return ret;
}
@@ -342,5 +422,19 @@ bool readJson(const crow::Request& req, crow::Response& res, const char* key,
return readJson(jsonRequest, res, key, in...);
}
+template <typename Type>
+bool getValueFromJsonObject(nlohmann::json& jsonData, const std::string& key,
+ Type& value)
+{
+ nlohmann::json jsonValue = jsonData[key];
+ if (jsonValue.is_null())
+ {
+ BMCWEB_LOG_DEBUG << "Key " << key << " not exist";
+ return false;
+ }
+
+ return details::unpackValue(jsonValue, key, value);
+}
+
} // namespace json_util
} // namespace redfish