Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions src/rfl/json/to_schema.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,18 @@ schema::Type type_to_json_schema_type(const parsing::schema::Type& _type,
const bool _no_required);

bool is_optional(const parsing::schema::Type& _t) {
const auto handle = [](const auto& _v) -> bool {
return _t.variant_.visit([&](const auto& _v) -> bool {
using T = std::remove_cvref_t<decltype(_v)>;
return std::is_same<T, parsing::schema::Type::Optional>();
};
return rfl::visit(handle, _t.variant_);
if constexpr (std::is_same_v<T, parsing::schema::Type::Description>) {
return is_optional(*_v.type_);

} else if constexpr (std::is_same_v<T, parsing::schema::Type::Validated>) {
return is_optional(*_v.type_);

} else {
return std::is_same_v<T, parsing::schema::Type::Optional>;
}
});
Comment on lines +35 to +46

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The lambda capture [&] is not necessary here as the lambda body does not access any variables from the enclosing scope. The recursive call to is_optional is a call to a free function and does not require a capture. It's good practice to use a non-capturing lambda [] when no captures are needed as it can sometimes lead to better compiler optimizations.

Suggested change
return _t.variant_.visit([&](const auto& _v) -> bool {
using T = std::remove_cvref_t<decltype(_v)>;
return std::is_same<T, parsing::schema::Type::Optional>();
};
return rfl::visit(handle, _t.variant_);
if constexpr (std::is_same_v<T, parsing::schema::Type::Description>) {
return is_optional(*_v.type_);
} else if constexpr (std::is_same_v<T, parsing::schema::Type::Validated>) {
return is_optional(*_v.type_);
} else {
return std::is_same_v<T, parsing::schema::Type::Optional>;
}
});
return _t.variant_.visit([](const auto& _v) -> bool {
using T = std::remove_cvref_t<decltype(_v)>;
if constexpr (std::is_same_v<T, parsing::schema::Type::Description>) {
return is_optional(*_v.type_);
} else if constexpr (std::is_same_v<T, parsing::schema::Type::Validated>) {
return is_optional(*_v.type_);
} else {
return std::is_same_v<T, parsing::schema::Type::Optional>;
}
});

}

std::string numeric_type_to_string(const parsing::schema::Type& _type) {
Expand Down
32 changes: 32 additions & 0 deletions tests/json/test_json_schema5.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#include <iostream>
#include <optional>
#include <rfl.hpp>
#include <rfl/json.hpp>
#include <string>
#include <tuple>
#include <vector>

#include "write_and_read.hpp"

namespace test_json_schema5 {

using Age = rfl::Validator<std::optional<unsigned int>, rfl::Minimum<0>,
rfl::Maximum<130>>;

struct Person {
rfl::Description<"Given name of this person", std::string> first_name;
rfl::Description<"Optional family name of this person",
std::optional<std::string>>
last_name;
Age age;
};

TEST(json, test_json_schema5) {
const auto json_schema = rfl::json::to_schema<Person>();

const std::string expected =
R"({"$schema":"https://json-schema.org/draft/2020-12/schema","$ref":"#/definitions/test_json_schema5__Person","definitions":{"test_json_schema5__Person":{"type":"object","properties":{"first_name":{"type":"string","description":"Given name of this person"},"last_name":{"description":"Optional family name of this person","anyOf":[{"type":"string"},{"type":"null"}]},"age":{"allOf":[{"minimum":0,"type":"number"},{"maximum":130,"type":"number"}]}},"required":["first_name"]}}})";

EXPECT_EQ(json_schema, expected);
}
} // namespace test_json_schema5
Loading