diff --git a/README.md b/README.md index ab42327..0554bf8 100644 --- a/README.md +++ b/README.md @@ -111,15 +111,34 @@ void parsing() auto opt_v = value.find("not_exists"); std::cout << "Did we find the \"not_exists\"? " << opt_v.has_value() << std::endl; - std::vector to_vec = value["list"].to_vector(); - std::list to_list = value["list"].to_vector(); - std::set to_set = value["list"].to_vector(); + bool is_vec = value["list"].is>(); + + std::vector to_vec = value["list"].as_collection(); + to_vec = (std::vector)value["list"]; // same as above + to_vec = value["list"].as>(); // same as above + // Output: 1, 2, 3 for (auto&& i : to_vec) { std::cout << i << std::endl; } - std::map to_map = value["author"].to_map(); - auto to_hashmap = value["author"].to_map(); + + std::list to_list = value["list"].as_collection(); + to_list = (std::list)value["list"]; // same as above + to_list = value["list"].as>(); // same as above + + std::set to_set = value["list"].as_collection(); + to_set = (std::set)value["list"]; // same as above + to_set = value["list"].as>(); // same as above + + bool is_map = value["author"].is>(); + + std::map to_map = value["author"].as_map(); + to_map = (std::map)value["author"]; // same as above + to_map = value["author"].as>(); // same as above + + auto to_hashmap = value["author"].as_map(); + to_hashmap = (std::unordered_map)value["author"]; // same as above + to_hashmap = value["author"].as>();// same as above // Output: "literals" using namespace json::literals; diff --git a/README_en.md b/README_en.md index a0f1699..9abab83 100644 --- a/README_en.md +++ b/README_en.md @@ -111,15 +111,34 @@ void parsing() auto opt_v = value.find("not_exists"); std::cout << "Did we find the \"not_exists\"? " << opt_v.has_value() << std::endl; - std::vector to_vec = value["list"].to_vector(); - std::list to_list = value["list"].to_vector(); - std::set to_set = value["list"].to_vector(); + bool is_vec = value["list"].is>(); + + std::vector to_vec = value["list"].as_collection(); + to_vec = (std::vector)value["list"]; // same as above + to_vec = value["list"].as>(); // same as above + // Output: 1, 2, 3 for (auto&& i : to_vec) { std::cout << i << std::endl; } - std::map to_map = value["author"].to_map(); - auto to_hashmap = value["author"].to_map(); + + std::list to_list = value["list"].as_collection(); + to_list = (std::list)value["list"]; // same as above + to_list = value["list"].as>(); // same as above + + std::set to_set = value["list"].as_collection(); + to_set = (std::set)value["list"]; // same as above + to_set = value["list"].as>(); // same as above + + bool is_map = value["author"].is>(); + + std::map to_map = value["author"].as_map(); + to_map = (std::map)value["author"]; // same as above + to_map = value["author"].as>(); // same as above + + auto to_hashmap = value["author"].as_map(); + to_hashmap = (std::unordered_map)value["author"]; // same as above + to_hashmap = value["author"].as>();// same as above // Output: "literals" using namespace json::literals; diff --git a/include/json.hpp b/include/json.hpp index 4790ae2..2fd001f 100644 --- a/include/json.hpp +++ b/include/json.hpp @@ -43,6 +43,22 @@ namespace utils using iter_value_t = typename std::iterator_traits>::value_type; template using range_value_t = iter_value_t>; + + template + constexpr bool is_container = false; + template + constexpr bool is_container>> = + std::is_same_v>; + + template + constexpr bool is_map = false; + template + constexpr bool is_map> = is_container; + + template + constexpr bool is_collection = false; + template + constexpr bool is_collection = is_container && !is_map; } // ********************************* @@ -132,6 +148,9 @@ class basic_value template bool is() const noexcept; + template + bool all() const; + bool contains(const string_t& key) const; bool contains(size_t pos) const; bool exists(const string_t& key) const { return contains(key); } @@ -165,6 +184,12 @@ class basic_value string_t as_string() const; const basic_array& as_array() const; const basic_object& as_object() const; + + template typename collection_t = std::vector> + collection_t as_collection() const; + template typename map_t = std::map> + map_t as_map() const; + template value_t as() const; @@ -194,12 +219,18 @@ class basic_value return format(indent, 0); } - template - bool all() const; template typename vector_t = std::vector> - vector_t to_vector() const; + // deprecated, please use `as_collection` instead. + vector_t to_vector() const + { + return to_vector(); + } template typename map_t = std::map> - map_t to_map() const; + // deprecated, please use `as_map` instead. + map_t to_map() const + { + return as_map(); + } basic_value& operator=(const basic_value& rhs); basic_value& operator=(basic_value&&) noexcept; @@ -240,6 +271,19 @@ class basic_value explicit operator long double() const { return as_long_double(); } explicit operator string_t() const { return as_string(); } + template typename collection_t = std::vector, + typename _ = std::enable_if_t>>> + explicit operator collection_t() const + { + return as_collection(); + } + template typename map_t = std::map, + typename _ = std::enable_if_t>>> + explicit operator map_t() const + { + return as_map(); + } + private: friend class basic_array; friend class basic_object; @@ -317,8 +361,8 @@ class basic_array } template bool all() const; - template typename vector_t = std::vector> - vector_t to_vector() const; + template typename collection_t = std::vector> + collection_t as_collection() const; // Usage: get(key_1, key_2, ..., default_value); template @@ -432,7 +476,7 @@ class basic_object template bool all() const; template typename map_t = std::map> - map_t to_map() const; + map_t as_map() const; // Usage: get(key_1, key_2, ..., default_value); template @@ -733,19 +777,26 @@ inline bool basic_value::is() const noexcept return true; } else if constexpr (std::is_same_v) { - return _type == value_type::boolean; + return is_boolean(); } else if constexpr (std::is_arithmetic_v) { - return _type == value_type::number; + return is_number(); } else if constexpr (std::is_same_v, value_t>) { - return _type == value_type::array; + return is_array(); + } + else if constexpr (utils::is_collection) { + return is_array() && all(); } else if constexpr (std::is_same_v, value_t>) { - return _type == value_type::object; + return is_object(); + } + else if constexpr (utils::is_map) { + return is_object() && std::is_constructible_v && + all(); } else if constexpr (std::is_constructible_v) { - return _type == value_type::string; + return is_string(); } else { static_assert(!sizeof(value_t), "Unsupported type"); @@ -1174,17 +1225,17 @@ inline bool basic_value::all() const } template -template typename vector_t> -inline vector_t basic_value::to_vector() const +template typename collection_t> +inline collection_t basic_value::as_collection() const { - return as_array().template to_vector(); + return as_array().template as_collection(); } template template typename map_t> -inline map_t basic_value::to_map() const +inline map_t basic_value::as_map() const { - return as_object().template to_map(); + return as_object().template as_map(); } template @@ -1465,7 +1516,7 @@ inline bool basic_array::all() const return true; } -namespace _to_vector_helper +namespace _as_collection_helper { template class has_emplace_back @@ -1482,12 +1533,12 @@ namespace _to_vector_helper } template -template typename vector_t> -inline vector_t basic_array::to_vector() const +template typename collection_t> +inline collection_t basic_array::as_collection() const { - vector_t result; - if constexpr (_to_vector_helper::has_emplace_back>::value) { + collection_t result; + if constexpr (_as_collection_helper::has_emplace_back>::value) { for (const auto& elem : _array_data) { result.emplace_back(elem.template as()); } @@ -1819,7 +1870,7 @@ inline bool basic_object::all() const template template typename map_t> -inline map_t basic_object::to_map() const +inline map_t basic_object::as_map() const { map_t result; for (const auto& [key, val] : _object_data) { @@ -2586,22 +2637,6 @@ namespace _serialization_helper static constexpr bool value = decltype(test(0))::value; }; - template - constexpr bool is_container = false; - template - constexpr bool is_container>> = - std::is_same_v>; - - template - constexpr bool is_map = false; - template - constexpr bool is_map> = is_container; - - template - constexpr bool is_collection = false; - template - constexpr bool is_collection = is_container && !is_map; - template struct string_converter { @@ -2664,7 +2699,7 @@ basic_value serialize(any_t&& arg, string_converter_t&& string_convert else if constexpr (std::decay_t::template is_convertible) { return string_converter(std::forward(arg)); } - else if constexpr (is_collection>) { + else if constexpr (utils::is_collection>) { basic_value result; for (auto&& val : arg) { using value_t = decltype(val); @@ -2674,7 +2709,7 @@ basic_value serialize(any_t&& arg, string_converter_t&& string_convert } return result; } - else if constexpr (is_map>) { + else if constexpr (utils::is_map>) { basic_value result; for (auto&& [key, val] : arg) { using key_t = decltype(key); diff --git a/sample/sample.cpp b/sample/sample.cpp index f893295..e00c3be 100644 --- a/sample/sample.cpp +++ b/sample/sample.cpp @@ -3,8 +3,8 @@ #include #include #include -#include #include +#include #include "json.hpp" @@ -103,16 +103,36 @@ bool parsing() auto opt_v = value.find("not_exists"); std::cout << "Did we find the \"not_exists\"? " << opt_v.has_value() << std::endl; - std::vector to_vec = value["list"].to_vector(); - std::list to_list = value["list"].to_vector(); - std::set to_set = value["list"].to_vector(); - // Output: 1, 2, 3 - for (auto&& i : to_vec) { - std::cout << i << std::endl; + bool is_vec = value["list"].is>(); + if (is_vec) { + std::vector to_vec = value["list"].as_collection(); + to_vec = (std::vector)value["list"]; + to_vec = value["list"].as>(); + + // Output: 1, 2, 3 + for (auto&& i : to_vec) { + std::cout << i << std::endl; + } + } + + std::list to_list = value["list"].as_collection(); + to_list = (std::list)value["list"]; + to_list = value["list"].as>(); + + std::set to_set = value["list"].as_collection(); + to_set = (std::set)value["list"]; + to_set = value["list"].as>(); + + bool is_map = value["author"].is>(); + if (is_map) { + std::map to_map = value["author"].as_map(); + to_map = (std::map)value["author"]; + to_map = value["author"].as>(); } - std::map to_map = value["author"].to_map(); - auto to_hashmap = value["author"].to_map(); + auto to_hashmap = value["author"].as_map(); + to_hashmap = (std::unordered_map)value["author"]; + to_hashmap = value["author"].as>(); using namespace json::literals; json::value val = "{\"hi\":\"literals\"}"_json; diff --git a/test/serializing_test.cpp b/test/serializing_test.cpp index ae094f9..e7bd1a9 100644 --- a/test/serializing_test.cpp +++ b/test/serializing_test.cpp @@ -43,13 +43,13 @@ bool serializing() std::cerr << "not all int: " << root["arr"].as_string() << std::endl; return false; } - auto to_vec = root["arr"].to_vector(); - auto to_vec_2 = root["arr"].to_vector(); - auto to_list = root["arr"].to_vector(); - auto to_set = root["arr"].to_vector(); - auto to_hashset = root["arr"].to_vector(); - auto to_deque = root["arr"].to_vector(); - auto to_q = root["arr"].to_vector(); + auto to_vec = root["arr"].as_collection(); + auto to_vec_2 = root["arr"].as_collection(); + auto to_list = root["arr"].as_collection(); + auto to_set = root["arr"].as_collection(); + auto to_hashset = root["arr"].as_collection(); + auto to_deque = root["arr"].as_collection(); + auto to_q = root["arr"].as_collection(); std::vector vec = { 1, 2, 3, 4, 5 }; @@ -69,9 +69,9 @@ bool serializing() std::cerr << "not all int: " << root["obj from map"].as_string() << std::endl; return false; } - auto to_map = root["obj from map"].to_map(); - auto to_map_2 = root["obj from map"].to_map(); - auto to_hashmap = root["obj from map"].to_map(); + auto as_map = root["obj from map"].as_map(); + auto as_map_2 = root["obj from map"].as_map(); + auto to_hashmap = root["obj from map"].as_map(); std::vector>> complex { { { 1, 2, 3 }, { 4, 5 } }, { { 6 }, { 7, 8 } } }; root["complex"] = json::serialize(complex);