diff --git a/include/glaze/json/json_t.hpp b/include/glaze/json/json_t.hpp index 81e823c789..1d2c4fbc0e 100644 --- a/include/glaze/json/json_t.hpp +++ b/include/glaze/json/json_t.hpp @@ -23,31 +23,31 @@ namespace glz val_t data{}; template - T& get() + [[nodiscard]] T& get() { return std::get(data); } template - const T& get() const + [[nodiscard]] const T& get() const { return std::get(data); } template - T* get_if() noexcept + [[nodiscard]] T* get_if() noexcept { return std::get_if(&data); } template - const T* get_if() const noexcept + [[nodiscard]] const T* get_if() const noexcept { return std::get_if(&data); } template - bool holds() const noexcept + [[nodiscard]] bool holds() const noexcept { return std::holds_alternative(data); } @@ -79,11 +79,11 @@ namespace glz return iter->second; } - json_t& at(std::convertible_to auto&& key) { return operator[](key); } + [[nodiscard]] json_t& at(std::convertible_to auto&& key) { return operator[](key); } - const json_t& at(std::convertible_to auto&& key) const { return operator[](key); } + [[nodiscard]] const json_t& at(std::convertible_to auto&& key) const { return operator[](key); } - bool contains(std::convertible_to auto&& key) const + [[nodiscard]] bool contains(std::convertible_to auto&& key) const { if (!holds()) return false; auto& object = std::get(data); @@ -145,7 +145,7 @@ namespace glz } template - T as() const + [[nodiscard]] T as() const { // Prefer get becuase it returns a reference return get(); @@ -153,7 +153,7 @@ namespace glz template requires std::convertible_to - T as() const + [[nodiscard]] T as() const { // Can be used for int and the like return static_cast(get()); @@ -161,12 +161,78 @@ namespace glz template requires std::convertible_to - T as() const + [[nodiscard]] T as() const { // Can be used for string_view and the like return get(); } + + [[nodiscard]] bool is_array() const noexcept { + return holds(); + } + + [[nodiscard]] bool is_object() const noexcept { + return holds(); + } + + [[nodiscard]] bool is_number() const noexcept { + return holds(); + } + + [[nodiscard]] bool is_string() const noexcept { + return holds(); + } + + [[nodiscard]] bool is_null() const noexcept { + return holds(); + } + + // empty() returns true if the value is an empty JSON object, array, or string, or a null value + // otherwise returns false + [[nodiscard]] bool empty() const noexcept { + if (auto* v = get_if(); v) { + return v->empty(); + } + else if (auto* v = get_if(); v) { + return v->empty(); + } + else if (auto* v = get_if(); v) { + return v->empty(); + } + else if (is_null()) { + return true; + } + else { + return false; + } + } + + // returns the count of items in an object or an array, or the size of a string, otherwise returns zero + [[nodiscard]] size_t size() const noexcept { + if (auto* v = get_if(); v) { + return v->size(); + } + else if (auto* v = get_if(); v) { + return v->size(); + } + else if (auto* v = get_if(); v) { + return v->size(); + } + else { + return 0; + } + } }; + + [[nodiscard]] inline bool is_array(const json_t& value) { return value.is_array(); } + + [[nodiscard]] inline bool is_object(const json_t& value) { return value.is_object(); } + + [[nodiscard]] inline bool is_number(const json_t& value) { return value.is_number(); } + + [[nodiscard]] inline bool is_string(const json_t& value) { return value.is_string(); } + + [[nodiscard]] inline bool is_null(const json_t& value) { return value.is_null(); } } template <> diff --git a/tests/json_test/json_test.cpp b/tests/json_test/json_test.cpp index 173c81c893..58eb3a60fe 100644 --- a/tests/json_test/json_test.cpp +++ b/tests/json_test/json_test.cpp @@ -3112,6 +3112,78 @@ suite generic_json_tests = [] { expect(not glz::write_json(glz::json_t(*(glz::read_json("{}"))), s)); expect(s == "{}") << s; }; + + "json_t is_object"_test = [] { + glz::json_t json{}; + expect(not glz::read_json(json, "{}")); + expect(json.is_object()); + expect(glz::is_object(json)); + expect(json.empty()); + expect(json.size() == 0); + }; + + "json_t is_object"_test = [] { + glz::json_t json{}; + expect(not glz::read_json(json, R"({"age":"22","name":"Noah"})")); + expect(json.is_object()); + expect(glz::is_object(json)); + expect(not json.empty()); + expect(json.size() == 2); + }; + + "json_t is_array"_test = [] { + glz::json_t json{}; + expect(not glz::read_json(json, "[]")); + expect(json.is_array()); + expect(glz::is_array(json)); + expect(json.empty()); + expect(json.size() == 0); + }; + + "json_t is_array"_test = [] { + glz::json_t json{}; + expect(not glz::read_json(json, "[1,2,3]")); + expect(json.is_array()); + expect(glz::is_array(json)); + expect(not json.empty()); + expect(json.size() == 3); + }; + + "json_t is_string"_test = [] { + glz::json_t json{}; + expect(not glz::read_json(json, R"("")")); + expect(json.is_string()); + expect(glz::is_string(json)); + expect(json.empty()); + expect(json.size() == 0); + }; + + "json_t is_string"_test = [] { + glz::json_t json{}; + expect(not glz::read_json(json, R"("Beautiful beginning")")); + expect(json.is_string()); + expect(glz::is_string(json)); + expect(not json.empty()); + expect(json.size() == 19); + }; + + "json_t is_number"_test = [] { + glz::json_t json{}; + expect(not glz::read_json(json, "3.882e2")); + expect(json.is_number()); + expect(glz::is_number(json)); + expect(not json.empty()); + expect(json.size() == 0); + }; + + "json_t is_null"_test = [] { + glz::json_t json{}; + expect(not glz::read_json(json, "null")); + expect(json.is_null()); + expect(glz::is_null(json)); + expect(json.empty()); + expect(json.size() == 0); + }; }; struct holder0_t @@ -4413,12 +4485,6 @@ suite validation_tests = [] { expect(ec_fail17 != glz::error_code::none); expect(glz::validate_json(fail17) != glz::error_code::none); - // JSON spec does not specify a nesting limit to my knowledge - // std::string fail18 = R"([[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]])"; - // auto ec_fail18 = glz::read(json, fail18); - // expect(ec_fail18 != glz::error_code::none); - // expect(glz::validate_json(fail18) != glz::error_code::none); - std::string fail19 = R"({"Missing colon" null})"; auto ec_fail19 = glz::read(json, fail19); expect(ec_fail19 != glz::error_code::none);