diff options
author | AppaRao Puli <apparao.puli@linux.intel.com> | 2020-05-19 21:43:22 +0300 |
---|---|---|
committer | AppaRao Puli <apparao.puli@linux.intel.com> | 2020-05-29 21:26:14 +0300 |
commit | 471a5eb867c6a3e625bc5745edac8e56ad2e549c (patch) | |
tree | eded03aaa8f070b4d73d35da210418b0e554dd11 /redfish-core | |
parent | 2056b6d167a3ecb3c1615d906624a91259dc6c1f (diff) | |
download | bmcweb-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.hpp | 168 |
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 |