Skip to content

Commit

Permalink
Add from_sequence (yaml) and from_array (json)
Browse files Browse the repository at this point in the history
  • Loading branch information
k0zmo committed Sep 25, 2020
1 parent 746044b commit d4380d1
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 0 deletions.
43 changes: 43 additions & 0 deletions include/kl/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,44 @@ class object_extractor
private:
const rapidjson::Value& value_;
};

class array_extractor
{
public:
explicit array_extractor(const rapidjson::Value& value) : value_{value}
{
json::expect_array(value_);
}

template <typename T>
array_extractor& extract(T& out, unsigned index)
{
index_ = index;
return extract<T>(out);
}

template <typename T>
array_extractor& extract(T& out)
{
try
{
json::deserialize(out, json::at(value_.GetArray(), index_));
++index_;
return *this;
}
catch (deserialize_error& ex)
{
std::string msg =
"error when deserializing element " + std::to_string(index_);
ex.add(msg.c_str());
throw;
}
}

private:
const rapidjson::Value& value_;
unsigned index_{};
};
} // namespace detail

template <typename Context>
Expand All @@ -380,6 +418,11 @@ auto to_object(Context& ctx)
return detail::object_builder<Context>{ctx};
}

inline auto from_array(const rapidjson::Value& value)
{
return detail::array_extractor{value};
}

inline auto from_object(const rapidjson::Value& value)
{
return detail::object_extractor{value};
Expand Down
43 changes: 43 additions & 0 deletions include/kl/yaml.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,44 @@ class map_extractor
private:
const YAML::Node& node_;
};

class sequence_extractor
{
public:
explicit sequence_extractor(const YAML::Node& node) : node_{node}
{
yaml::expect_sequence(node_);
}

template <typename T>
sequence_extractor& extract(T& out, unsigned index)
{
index_ = index;
return extract<T>(out);
}

template <typename T>
sequence_extractor& extract(T& out)
{
try
{
yaml::deserialize(out, yaml::at(node_, index_));
++index_;
return *this;
}
catch (deserialize_error& ex)
{
std::string msg =
"error when deserializing element " + std::to_string(index_);
ex.add(msg.c_str());
throw;
}
}

private:
const YAML::Node& node_;
unsigned index_{};
};
} // namespace detail

template <typename Context>
Expand All @@ -296,6 +334,11 @@ auto to_map(Context& ctx)
return detail::map_builder<Context>{ctx};
}

inline auto from_sequence(const YAML::Node& node)
{
return detail::sequence_extractor{node};
}

inline auto from_map(const YAML::Node& node)
{
return detail::map_extractor{node};
Expand Down
29 changes: 29 additions & 0 deletions tests/json_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1187,3 +1187,32 @@ TEST_CASE("json: to_array and to_object")
R"({"ctx":22,"values":[{"a":"asd","b":3,"c":true,"d":[1,2,34]},)"
R"({"a":"zxc","b":222,"c":false,"d":[1]}]})");
}

TEST_CASE("json: from_array and from_object")
{
const auto j =
R"({"ctx":123,"array":[{"r":331,"d":5.6},{"something":true},3]})"_json;

int ctx;
kl::json::view av;
kl::json::from_object(j).extract("ctx", ctx).extract("array", av);
REQUIRE(ctx == 123);
const auto& jarr = kl::json::at(j.GetObject(), "array");
REQUIRE(jarr == av.value());

inner_t inn;
kl::json::view view;
int i;
kl::json::from_array(jarr).extract(inn).extract(view, 1).extract(i);
REQUIRE(inn.r == 331);
REQUIRE(inn.d == Approx(5.6));
REQUIRE(i == 3);

bool smth;
kl::json::from_object(view.value()).extract("something", smth);
REQUIRE(smth);

REQUIRE_THROWS_WITH(kl::json::from_array(jarr).extract(smth, 2),
"type must be a boolean but is a kNumberType\n"
"error when deserializing element 2");
}
37 changes: 37 additions & 0 deletions tests/yaml_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1186,3 +1186,40 @@ TEST_CASE("yaml: to_sequence and to_map")
CHECK(str == R"({ctx: 22, values: [{a: asd, b: 3, c: true, d: [1, 2, 34]})"
R"(, {a: zxc, b: 222, c: false, d: [1]}]})");
}

TEST_CASE("yaml: from_sequence and from_map")
{
const auto y =
R"(ctx: 123
array:
- r: 331
d: 5.6
- something: true
- 3)"_yaml;

int ctx;
kl::yaml::view av;
kl::yaml::from_map(y).extract("ctx", ctx).extract("array", av);
REQUIRE(ctx == 123);
const auto& yseq = kl::yaml::at(y, "array");
REQUIRE(yseq == av.value());

inner_t inn;
kl::yaml::view view;
int i;
kl::yaml::from_sequence(av.value())
.extract(inn)
.extract(view, 1)
.extract(i);
REQUIRE(inn.r == 331);
REQUIRE(inn.d == Approx(5.6));
REQUIRE(i == 3);

bool smth;
kl::yaml::from_map(view.value()).extract("something", smth);
REQUIRE(smth);

REQUIRE_THROWS_WITH(kl::yaml::from_sequence(av.value()).extract(smth, 2),
"yaml-cpp: error at line 6, column 5: bad conversion\n"
"error when deserializing element 2");
}

0 comments on commit d4380d1

Please sign in to comment.