diff --git a/include/rfl/parsing/Parser_default.hpp b/include/rfl/parsing/Parser_default.hpp index adc7708b..b2cc5551 100644 --- a/include/rfl/parsing/Parser_default.hpp +++ b/include/rfl/parsing/Parser_default.hpp @@ -193,7 +193,9 @@ struct Parser { } else if constexpr (internal::is_validator_v) { return make_validated(_definitions); - } else if constexpr (internal::has_reflection_type_v) { + } else if constexpr (internal::has_reflection_type_v || + internal::has_read_reflector || + internal::has_write_reflector) { return make_reference(_definitions); } else { @@ -235,13 +237,21 @@ struct Parser { std::map* _definitions) { using Type = schema::Type; const auto name = make_type_name(); + if (_definitions->find(name) == _definitions->end()) { (*_definitions)[name] = Type{Type::Integer{}}; // Placeholder to avoid infinite loop. + if constexpr (internal::has_reflection_type_v) { (*_definitions)[name] = Parser::to_schema( _definitions); + + } else if constexpr (internal::has_read_reflector || + internal::has_write_reflector) { + (*_definitions)[name] = Parser::ReflType, + ProcessorsType>::to_schema(_definitions); + } else { using NamedTupleType = internal::processed_t; (*_definitions)[name] = diff --git a/include/rfl/parsing/make_type_name.hpp b/include/rfl/parsing/make_type_name.hpp index 306520fc..5f2ed404 100644 --- a/include/rfl/parsing/make_type_name.hpp +++ b/include/rfl/parsing/make_type_name.hpp @@ -4,8 +4,7 @@ #include "../type_name_t.hpp" #include "is_tagged_union_wrapper.hpp" -namespace rfl { -namespace parsing { +namespace rfl::parsing { inline std::string replace_non_alphanumeric(std::string _str) { for (auto& ch : _str) { @@ -24,7 +23,6 @@ static std::string make_type_name() { } } -} // namespace parsing -} // namespace rfl +} // namespace rfl::parsing #endif diff --git a/tests/json/test_reflector_schema.cpp b/tests/json/test_reflector_schema.cpp new file mode 100644 index 00000000..625400e6 --- /dev/null +++ b/tests/json/test_reflector_schema.cpp @@ -0,0 +1,50 @@ +#include +#include +#include +#include +#include + +#include "write_and_read.hpp" + +namespace test_reflector_schema { + +struct Person { + std::string first_name = "Homer"; + std::string last_name = "Simpson"; +}; + +struct Parent : Person { + public: + std::vector children; +}; + +} // namespace test_reflector_schema + +namespace rfl { +template <> +struct Reflector { + struct ReflType { + std::string first_name; + std::string last_name; + std::vector children; + }; + + static ReflType from(const test_reflector_schema::Parent& v) { + return {v.first_name, v.last_name, v.children}; + } +}; +} // namespace rfl + +namespace test_reflector_schema { + +TEST(json, test_reflector_schema) { + const std::string expected = + R"({"$schema":"https://json-schema.org/draft/2020-12/schema","$ref":"#/$defs/test_reflector_schema__Parent","$defs":{"rfl__Reflector_test_reflector_schema__Parent___ReflType":{"type":"object","properties":{"first_name":{"type":"string"},"last_name":{"type":"string"},"children":{"type":"array","items":{"$ref":"#/$defs/test_reflector_schema__Person"}}},"required":["first_name","last_name","children"]},"test_reflector_schema__Parent":{"$ref":"#/$defs/rfl__Reflector_test_reflector_schema__Parent___ReflType"},"test_reflector_schema__Person":{"type":"object","properties":{"first_name":{"type":"string"},"last_name":{"type":"string"}},"required":["first_name","last_name"]}}})"; + + const std::string expected_windows = + R"({"$schema":"https://json-schema.org/draft/2020-12/schema","$ref":"#/$defs/test_reflector_schema__Parent","$defs":{"rfl__Reflector_struct_test_reflector_schema__Parent___ReflType":{"type":"object","properties":{"first_name":{"type":"string"},"last_name":{"type":"string"},"children":{"type":"array","items":{"$ref":"#/$defs/test_reflector_schema__Person"}}},"required":["first_name","last_name","children"]},"test_reflector_schema__Parent":{"$ref":"#/$defs/rfl__Reflector_struct_test_reflector_schema__Parent___ReflType"},"test_reflector_schema__Person":{"type":"object","properties":{"first_name":{"type":"string"},"last_name":{"type":"string"}},"required":["first_name","last_name"]}}})"; + + EXPECT_TRUE(rfl::json::to_schema() == expected || + rfl::json::to_schema() == expected_windows); +} +} // namespace test_reflector_schema