diff --git a/inferno/src/inferno/util/json.h b/inferno/src/inferno/util/json.h index 5fcc332..3842b23 100644 --- a/inferno/src/inferno/util/json.h +++ b/inferno/src/inferno/util/json.h @@ -111,7 +111,7 @@ namespace Inferno { return {}; } - // Check if property is array + // Check if property is array [] ASSERT(getValue(it).is_array(), "Json property is not an array '{}'", property); // Fill array with values @@ -126,6 +126,45 @@ namespace Inferno { } } + // Return vector if it has any items, uninitialized optional otherwise + return values.size() > 0 ? std::optional { values } : std::nullopt; + } + + template + static std::optional> parseObjectProperty(const json& json, const char* property, bool required, json::value_t check) + { + return parseObjectProperty(json, property, required, std::vector { check }); + } + + template + static std::optional> parseObjectProperty(const json& json, const char* property, bool required, std::vector checks) + { + bool exists; + json_const_iterator it; + + // Has property + exists = hasProperty(json, it, property); + ASSERT(!required || (required && exists), "Json could not find required property '{}'", property); + + if (!exists) { + return {}; + } + + // Check if property is an object {} + ASSERT(getValue(it).is_object(), "Json property is not an array '{}'", property); + + std::map values; + for (auto& [key, value] : getValue(it).items()) { + auto typedValue = getPropertyValue(value, checks); + if (typedValue) { + values.emplace(std::move(key), typedValue.value()); + } + else { + warnln("Json array property '{}' has type inconsistency", property); + } + } + + // Return map if it has any items, uninitialized optional otherwise return values.size() > 0 ? std::optional { values } : std::nullopt; } @@ -169,8 +208,33 @@ namespace Inferno { return parseArrayProperty(json, property, required, json::value_t::number_unsigned); } + static std::optional> parseDoubleObjectProperty(const json& json, const char* property, bool required) + { + return parseObjectProperty(json, property, required, std::vector { json::value_t::number_integer, json::value_t::number_unsigned, json::value_t::number_float }); + } + + static std::optional> parseIntegerObjectProperty(const json& json, const char* property, bool required) + { + return parseObjectProperty(json, property, required, json::value_t::number_integer); + } + + static std::optional> parseUnsignedObjectProperty(const json& json, const char* property, bool required) + { + return parseObjectProperty(json, property, required, json::value_t::number_unsigned); + } + }; } // namespace Inferno #endif // JSON_UTIL_H + +// JSON syntax: +// [ ] = std::map, array (ordered) +// { } = std::vector, object (unordered) +// "": = std::string, property (key -> value) +// true/false = bool, condition +// -3 = int64_t, number +// 5 = uint64_t, number +// 4.567 = double, number +// "thing" = std::string, text