Skip to content

Commit

Permalink
feat: to_vector & to_map support custom container type
Browse files Browse the repository at this point in the history
  • Loading branch information
MistEO committed Oct 27, 2023
1 parent dc98ba5 commit 77fca9b
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 30 deletions.
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,15 @@ 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<int> to_vec = value["list"].to_vector<int>();
std::list<int> to_list = value["list"].to_vector<int, std::list>();
std::set<int> to_set = value["list"].to_vector<int, std::set>();
// Output: 1, 2, 3
std::vector<int> vec = value["list"].to_vector<int>();
for (auto&& i : vec) {
for (auto&& i : to_vec) {
std::cout << i << std::endl;
}
std::map<std::string, std::string> to_map = value["author"].to_map<std::string>();
auto to_hashmap = value["author"].to_map<std::string, std::unordered_map>();

// Output: "literals"
using namespace json::literals;
Expand Down
8 changes: 6 additions & 2 deletions README_en.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,15 @@ 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<int> to_vec = value["list"].to_vector<int>();
std::list<int> to_list = value["list"].to_vector<int, std::list>();
std::set<int> to_set = value["list"].to_vector<int, std::set>();
// Output: 1, 2, 3
std::vector<int> vec = value["list"].to_vector<int>();
for (auto&& i : vec) {
for (auto&& i : to_vec) {
std::cout << i << std::endl;
}
std::map<std::string, std::string> to_map = value["author"].to_map<std::string>();
auto to_hashmap = value["author"].to_map<std::string, std::unordered_map>();

// Output: "literals"
using namespace json::literals;
Expand Down
69 changes: 47 additions & 22 deletions include/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,10 +193,11 @@ class basic_value
{
return format(indent, 0);
}
template <typename value_t>
std::vector<value_t> to_vector() const;
template <typename value_t>
std::map<string_t, value_t> to_map() const;

template <typename value_t, template <typename value_t> typename vector_t = std::vector>
vector_t<value_t> to_vector() const;
template <typename value_t, template <typename string_t, typename value_t> typename map_t = std::map>
map_t<string_t, value_t> to_map() const;

basic_value<string_t>& operator=(const basic_value<string_t>& rhs);
basic_value<string_t>& operator=(basic_value<string_t>&&) noexcept;
Expand Down Expand Up @@ -312,8 +313,8 @@ class basic_array
{
return format(indent, 0);
}
template <typename value_t>
std::vector<value_t> to_vector() const;
template <typename value_t, template <typename value_t> typename vector_t = std::vector>
vector_t<value_t> to_vector() const;

// Usage: get(key_1, key_2, ..., default_value);
template <typename... key_then_default_value_t>
Expand Down Expand Up @@ -424,8 +425,8 @@ class basic_object
{
return format(indent, 0);
}
template <typename value_t>
std::map<string_t, value_t> to_map() const;
template <typename value_t, template <typename string_t, typename value_t> typename map_t = std::map>
map_t<string_t, value_t> to_map() const;

// Usage: get(key_1, key_2, ..., default_value);
template <typename... key_then_default_value_t>
Expand Down Expand Up @@ -1152,17 +1153,17 @@ inline string_t basic_value<string_t>::format(size_t indent, size_t indent_times
}

template <typename string_t>
template <typename value_t>
inline std::vector<value_t> basic_value<string_t>::to_vector() const
template <typename value_t, template <typename value_t> typename vector_t>
inline vector_t<value_t> basic_value<string_t>::to_vector() const
{
return as_array().template to_vector<value_t>();
return as_array().template to_vector<value_t, vector_t>();
}

template <typename string_t>
template <typename value_t>
inline std::map<string_t, value_t> basic_value<string_t>::to_map() const
template <typename value_t, template <typename string_t, typename value_t> typename map_t>
inline map_t<string_t, value_t> basic_value<string_t>::to_map() const
{
return as_object().template to_map<value_t>();
return as_object().template to_map<value_t, map_t>();
}

template <typename string_t>
Expand Down Expand Up @@ -1431,13 +1432,37 @@ inline string_t basic_array<string_t>::format(size_t indent, size_t indent_times
return str;
}

namespace _to_vector_helper
{
template <typename T>
class has_emplace_back
{
template <typename U>
static auto test(int) -> decltype(std::declval<U>().emplace_back(), std::true_type());

template <typename U>
static std::false_type test(...);

public:
static constexpr bool value = decltype(test<T>(0))::value;
};
}

template <typename string_t>
template <typename value_t>
inline std::vector<value_t> basic_array<string_t>::to_vector() const
template <typename value_t, template <typename value_t> typename vector_t>
inline vector_t<value_t> basic_array<string_t>::to_vector() const
{
std::vector<value_t> result;
for (const auto& elem : _array_data) {
result.emplace_back(elem.template as<value_t>());

vector_t<value_t> result;
if constexpr (_to_vector_helper::has_emplace_back<vector_t<value_t>>::value) {
for (const auto& elem : _array_data) {
result.emplace_back(elem.template as<value_t>());
}
}
else {
for (const auto& elem : _array_data) {
result.emplace(elem.template as<value_t>());
}
}
return result;
}
Expand Down Expand Up @@ -1748,10 +1773,10 @@ inline string_t basic_object<string_t>::format(size_t indent, size_t indent_time
}

template <typename string_t>
template <typename value_t>
inline std::map<string_t, value_t> basic_object<string_t>::to_map() const
template <typename value_t, template <typename string_t, typename value_t> typename map_t>
inline map_t<string_t, value_t> basic_object<string_t>::to_map() const
{
std::map<string_t, value_t> result;
map_t<string_t, value_t> result;
for (const auto& [key, val] : _object_data) {
result.emplace(key, val.template as<value_t>());
}
Expand Down
10 changes: 8 additions & 2 deletions sample/sample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <map>
#include <set>
#include <vector>
#include <unordered_map>

#include "json.hpp"

Expand Down Expand Up @@ -102,12 +103,17 @@ 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<int> to_vec = value["list"].to_vector<int>();
std::list<int> to_list = value["list"].to_vector<int, std::list>();
std::set<int> to_set = value["list"].to_vector<int, std::set>();
// Output: 1, 2, 3
std::vector<int> vec = value["list"].to_vector<int>();
for (auto&& i : vec) {
for (auto&& i : to_vec) {
std::cout << i << std::endl;
}

std::map<std::string, std::string> to_map = value["author"].to_map<std::string>();
auto to_hashmap = value["author"].to_map<std::string, std::unordered_map>();

using namespace json::literals;
json::value val = "{\"hi\":\"literals\"}"_json;
std::cout << val["hi"] << std::endl;
Expand Down
16 changes: 14 additions & 2 deletions test/serializing_test.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
#include <array>
#include <deque>
#include <filesystem>
#include <iostream>
#include <list>
#include <queue>
#include <set>
#include <unordered_map>
#include <iostream>
#include <unordered_set>

#include "json.hpp"

Expand Down Expand Up @@ -35,7 +38,14 @@ bool serializing()
root["arr"].emplace(5);
root["arr"] += json::array { 6, 7 };

auto to_arr = root["arr"].to_vector<int>();
auto to_vec = root["arr"].to_vector<int>();
auto to_vec_2 = root["arr"].to_vector<int, std::vector>();
auto to_list = root["arr"].to_vector<int, std::list>();
auto to_set = root["arr"].to_vector<int, std::set>();
auto to_hashset = root["arr"].to_vector<int, std::unordered_set>();
auto to_deque = root["arr"].to_vector<int, std::deque>();
auto to_q = root["arr"].to_vector<int, std::queue>();


std::vector<int> vec = { 1, 2, 3, 4, 5 };
root["arr from vec"] = vec;
Expand All @@ -50,6 +60,8 @@ bool serializing()
root["obj from map"] = map;

auto to_map = root["obj from map"].to_map<int>();
auto to_map_2 = root["obj from map"].to_map<int, std::map>();
auto to_hashmap = root["obj from map"].to_map<int, std::unordered_map>();

std::vector<std::list<std::set<int>>> complex { { { 1, 2, 3 }, { 4, 5 } }, { { 6 }, { 7, 8 } } };
root["complex"] = json::serialize<false>(complex);
Expand Down

0 comments on commit 77fca9b

Please sign in to comment.