| #include "json_utils.h" |
| |
| #include <cstddef> |
| #include <cstdint> |
| #include <optional> |
| #include <string> |
| #include <string_view> |
| |
| #include "absl/log/log.h" |
| #include "absl/strings/numbers.h" |
| #include "absl/strings/str_cat.h" |
| #include "nlohmann/json.hpp" |
| |
| namespace milotic::authz { |
| namespace { |
| |
| template <typename ReturnType> |
| const ReturnType* GetValueAsType(const nlohmann::json& root, |
| std::string_view key, |
| [[maybe_unused]] std::string_view type_name) { |
| if (root.is_discarded()) { |
| LOG(WARNING) << "Invalid JSON object"; |
| return nullptr; |
| } |
| auto it = root.find(key); |
| if (it == root.end()) { |
| return nullptr; |
| } |
| if constexpr (std::is_same_v<ReturnType, nlohmann::json>) { |
| return &(*it); |
| } else { |
| return it->get_ptr<const ReturnType*>(); |
| } |
| } |
| } // namespace |
| |
| const std::string* GetValueAsString(const nlohmann::json& root, |
| std::string_view key) { |
| return GetValueAsType<std::string>(root, key, "string"); |
| } |
| |
| const std::string* GetValueAsString( |
| const nlohmann::json& root, const nlohmann::json::json_pointer& pointer) { |
| if (!root.contains(pointer)) { |
| return nullptr; |
| } |
| |
| return root[pointer].get_ptr<const std::string*>(); |
| } |
| |
| const nlohmann::json* GetValueAsJson(const nlohmann::json& root, |
| std::string_view key) { |
| return GetValueAsType<nlohmann::json>(root, key, "object"); |
| } |
| |
| const nlohmann::json::array_t* GetValueAsArray(const nlohmann::json& root, |
| std::string_view key) { |
| return GetValueAsType<nlohmann::json::array_t>(root, key, "array"); |
| } |
| |
| const double* GetValueAsDouble(const nlohmann::json& root, |
| std::string_view key) { |
| return GetValueAsType<nlohmann::json::number_float_t>(root, key, "number"); |
| } |
| |
| const int64_t* GetValueAsInt(const nlohmann::json& root, std::string_view key) { |
| return GetValueAsType<nlohmann::json::number_integer_t>(root, key, "number"); |
| } |
| |
| const bool* GetValueAsBool(const nlohmann::json& root, std::string_view key) { |
| return GetValueAsType<nlohmann::json::boolean_t>(root, key, "boolean"); |
| } |
| |
| const uint64_t* GetValueAsUint(const nlohmann::json& root, |
| std::string_view key) { |
| return GetValueAsType<nlohmann::json::number_unsigned_t>(root, key, "number"); |
| } |
| |
| // The following functions are used to parse from json where the type may vary |
| // and conversion is accepted. Return a value directly since a pointer cannot be |
| // made to the temporary value after being converted to desired type. |
| |
| std::optional<uint64_t> GetValueAsUintFromStringOrInteger( |
| const nlohmann::json& root, std::string_view key) { |
| const uint64_t* unsigned_ptr = |
| GetValueAsType<nlohmann::json::number_unsigned_t>(root, key, "number"); |
| if (unsigned_ptr != nullptr) { |
| return *unsigned_ptr; |
| } |
| |
| const std::string* string_ptr = |
| GetValueAsType<std::string>(root, key, "string"); |
| if (string_ptr == nullptr) { |
| LOG(INFO) << absl::StrCat("Invalid json: ", key, " field does not exist ", |
| root.dump()); |
| return std::nullopt; |
| } |
| |
| uint64_t unsigned_value; |
| bool result; |
| result = absl::SimpleAtoi(*string_ptr, &unsigned_value); |
| if (!result) { |
| LOG(INFO) << absl::StrCat("Invalid json: Failed to convert value at ", key, |
| " to unsigned value: ", root.dump()); |
| return std::nullopt; |
| } |
| LOG(INFO) << "Successfully converted string to unsigned value: " |
| << unsigned_value; |
| return unsigned_value; |
| } |
| |
| std::optional<double> GetValueAsDoubleFromFloatOrInteger( |
| const nlohmann::json& root, std::string_view key) { |
| const double* double_ptr = |
| GetValueAsType<nlohmann::json::number_float_t>(root, key, "number"); |
| if (double_ptr != nullptr) { |
| return *double_ptr; |
| } |
| |
| double double_value; |
| const uint64_t* unsigned_ptr = GetValueAsType<uint64_t>(root, key, "number"); |
| if (unsigned_ptr == nullptr) { |
| LOG(INFO) << absl::StrCat("Invalid json: Failed to convert value at ", key, |
| " to double ", root.dump()); |
| return std::nullopt; |
| } |
| |
| double_value = static_cast<double>(*unsigned_ptr); |
| LOG(INFO) << "Successfully converted integer to unsigned value: " |
| << double_value; |
| return double_value; |
| } |
| |
| const std::string* GetValueAsStringFromArray( |
| const nlohmann::json::array_t& array, std::size_t index) { |
| if (index >= array.size()) { |
| LOG(INFO) << absl::StrCat("Invalid index: Index ", index, |
| " is out of range for array of size ", |
| array.size()); |
| return nullptr; |
| } |
| return array[index].get_ptr<const std::string*>(); |
| } |
| |
| } // namespace milotic::authz |