diff --git a/chaotic/include/userver/chaotic/ref.hpp b/chaotic/include/userver/chaotic/ref.hpp index 97ef92d81c60..48a0a9d64eca 100644 --- a/chaotic/include/userver/chaotic/ref.hpp +++ b/chaotic/include/userver/chaotic/ref.hpp @@ -30,6 +30,16 @@ void WriteToStream(const Ref& ps, formats::json::StringBuilder& sw) { WriteToStream(T{*ps.value}, sw); } +template +void WriteToStream( + const Ref& ps, + formats::json::StringBuilder& sw, + bool hide_brackets, + std::string_view hide_field_name +) { + WriteToStream(T{*ps.value}, sw, hide_brackets, hide_field_name); +} + } // namespace chaotic USERVER_NAMESPACE_END diff --git a/chaotic/include/userver/chaotic/sax_parser.hpp b/chaotic/include/userver/chaotic/sax_parser.hpp index e683ae56f437..d1a714397dea 100644 --- a/chaotic/include/userver/chaotic/sax_parser.hpp +++ b/chaotic/include/userver/chaotic/sax_parser.hpp @@ -104,8 +104,10 @@ class WithValidators final : private formats::json::parser::Subscriber> class RefParser final : private formats::json::parser::Subscriber { public: + using Subparser = chaotic::sax::Parser; + RefParser() - : parser_(std::make_unique>()) + : parser_(std::make_unique()) { parser_->Subscribe(*this); } @@ -114,12 +116,12 @@ class RefParser final : private formats::json::parser::Subscriber { void Subscribe(formats::json::parser::Subscriber>& subscriber) { subscriber_ = &subscriber; } - formats::json::parser::BaseParser& GetParser() { return *parser_; } + formats::json::parser::BaseParser& GetParser() { return parser_->GetParser(); } + void OnSend(ResultType&& value) override { subscriber_->OnSend(utils::Box(std::move(value))); } private: - void OnSend(ResultType&& value) { subscriber_->OnSend(utils::Box(std::move(value))); } - std::unique_ptr> parser_; + std::unique_ptr parser_; formats::json::parser::Subscriber>* subscriber_{nullptr}; }; diff --git a/chaotic/integration_tests/schemas/oneof_discriminator_indirect.yaml b/chaotic/integration_tests/schemas/oneof_discriminator_indirect.yaml new file mode 100644 index 000000000000..b1e1826a1154 --- /dev/null +++ b/chaotic/integration_tests/schemas/oneof_discriminator_indirect.yaml @@ -0,0 +1,43 @@ +definitions: + Tree: + type: object + additionalProperties: false + required: + - root + properties: + root: + $ref: '#/definitions/Node' + x-usrv-cpp-indirect: true + + Node: + oneOf: + - $ref: '#/definitions/TypeA' + x-usrv-cpp-indirect: true + - $ref: '#/definitions/TypeB' + x-usrv-cpp-indirect: true + discriminator: + propertyName: kind + mapping: + 1: '#/definitions/TypeA' + 2: '#/definitions/TypeB' + + TypeA: + type: object + required: + - kind + properties: + kind: + type: integer + value: + type: integer + + TypeB: + type: object + required: + - kind + properties: + kind: + type: integer + nested: + $ref: '#/definitions/Node' + x-usrv-cpp-indirect: true diff --git a/chaotic/integration_tests/tests/render/oneof_discriminator_indirect.cpp b/chaotic/integration_tests/tests/render/oneof_discriminator_indirect.cpp new file mode 100644 index 000000000000..67f95be88eb0 --- /dev/null +++ b/chaotic/integration_tests/tests/render/oneof_discriminator_indirect.cpp @@ -0,0 +1,51 @@ +#include + +#include +#include +#include + +#include + +#include "helper.hpp" + +USERVER_NAMESPACE_BEGIN + +TEST(OneOfDiscriminatorIndirect, ParseSimpleVariant) { + const auto json = formats::json::MakeObject( + "root", + formats::json::MakeObject("kind", 1, "value", 42) + ); + auto tree = json.As(); + + EXPECT_TRUE(std::holds_alternative>(*tree.root)); + EXPECT_EQ(std::get>(*tree.root)->value, 42); + + EXPECT_EQ(TestDomSerializer(tree), json); + EXPECT_EQ(TestWriteToStream(tree), json); +} + +TEST(OneOfDiscriminatorIndirect, ParseVariantWithIndirectNested) { + const auto json = formats::json::MakeObject( + "root", + formats::json::MakeObject( + "kind", 2, + "nested", formats::json::MakeObject( + "kind", 1, + "value", 100 + ) + ) + ); + auto tree = json.As(); + EXPECT_TRUE(std::holds_alternative>(*tree.root)); + + auto& type_b = std::get>(*tree.root); + EXPECT_TRUE(type_b->nested.has_value()); + EXPECT_TRUE(std::holds_alternative>(*type_b->nested.value())); + EXPECT_EQ(std::get>(*type_b->nested.value())->value, 100); + + + EXPECT_EQ(TestDomSerializer(tree), json); + EXPECT_EQ(TestWriteToStream(tree), json); +} + +USERVER_NAMESPACE_END