diff options
author | AlexSm <alex@ydb.tech> | 2023-12-22 20:30:08 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-12-22 20:30:08 +0100 |
commit | 6b4f46a6883f21c16eef367106167ea59932515e (patch) | |
tree | 5833709b16bba3948f15e88b9038229c5065605b /library/cpp/protobuf/json | |
parent | a8b737f2a6df02f6e45ed703246c75f0f4cf7a34 (diff) | |
download | ydb-6b4f46a6883f21c16eef367106167ea59932515e.tar.gz |
Import libs 3 (#679)
Diffstat (limited to 'library/cpp/protobuf/json')
-rw-r--r-- | library/cpp/protobuf/json/json_writer_output.h | 5 | ||||
-rw-r--r-- | library/cpp/protobuf/json/proto2json_printer.cpp | 10 | ||||
-rw-r--r-- | library/cpp/protobuf/json/proto2json_printer.h | 2 | ||||
-rw-r--r-- | library/cpp/protobuf/json/ut/proto2json_ut.cpp | 44 | ||||
-rw-r--r-- | library/cpp/protobuf/json/ut/string_transform_ut.cpp | 2 |
5 files changed, 53 insertions, 10 deletions
diff --git a/library/cpp/protobuf/json/json_writer_output.h b/library/cpp/protobuf/json/json_writer_output.h index 3d8a2daa56..975245a264 100644 --- a/library/cpp/protobuf/json/json_writer_output.h +++ b/library/cpp/protobuf/json/json_writer_output.h @@ -86,7 +86,7 @@ namespace NProtobufJson { { } - private: + protected: static NJson::TJsonWriterConfig CreateJsonWriterConfig(const TProto2JsonConfig& cfg); }; @@ -95,7 +95,8 @@ namespace NProtobufJson { template <typename TConfig> TJsonStringWriterOutput(TString* str, const TConfig& cfg) : TEmbedPolicy<TStringOutput>(*str) - , TJsonWriterOutput(TEmbedPolicy<TStringOutput>::Ptr(), cfg) + // If Unbuffered = false, TJsonWriter uses its own string and then flushes it into TStringOutput. + , TJsonWriterOutput(TEmbedPolicy<TStringOutput>::Ptr(), CreateJsonWriterConfig(cfg).SetUnbuffered(true)) { } }; diff --git a/library/cpp/protobuf/json/proto2json_printer.cpp b/library/cpp/protobuf/json/proto2json_printer.cpp index 456d1c43c5..aa0823de0e 100644 --- a/library/cpp/protobuf/json/proto2json_printer.cpp +++ b/library/cpp/protobuf/json/proto2json_printer.cpp @@ -195,6 +195,9 @@ namespace NProtobufJson { using namespace google::protobuf; auto type = proto.GetDescriptor()->well_known_type(); + // XXX static_cast will cause UB if used with dynamic messages + // (can be created by a DynamicMessageFactory with SetDelegateToGeneratedFactory(false). Unlikely, but still possible). + // See workaround with CopyFrom in JsonString2Duration, JsonString2Timestamp (json2proto.cpp) if (type == Descriptor::WellKnownType::WELLKNOWNTYPE_DURATION) { const auto& duration = static_cast<const Duration&>(proto); json.Write(util::TimeUtil::ToString(duration)); @@ -210,7 +213,8 @@ namespace NProtobufJson { void TProto2JsonPrinter::PrintSingleField(const Message& proto, const FieldDescriptor& field, IJsonOutput& json, - TStringBuf key) { + TStringBuf key, + bool inProtoMap) { Y_ABORT_UNLESS(!field.is_repeated(), "field is repeated."); if (!key) { @@ -236,7 +240,7 @@ namespace NProtobufJson { const Reflection* reflection = proto.GetReflection(); - bool shouldPrintField = reflection->HasField(proto, &field); + bool shouldPrintField = inProtoMap || reflection->HasField(proto, &field); if (!shouldPrintField && GetConfig().MissingSingleKeyMode == TProto2JsonConfig::MissingKeyExplicitDefaultThrowRequired) { if (field.has_default_value()) { shouldPrintField = true; @@ -409,7 +413,7 @@ namespace NProtobufJson { TString key = MakeKey(proto, *keyField); const FieldDescriptor* valueField = proto.GetDescriptor()->FindFieldByName("value"); Y_ABORT_UNLESS(valueField, "Map entry value field not found."); - PrintField(proto, *valueField, json, key); + PrintSingleField(proto, *valueField, json, key, true); } TString TProto2JsonPrinter::MakeKey(const NProtoBuf::Message& proto, diff --git a/library/cpp/protobuf/json/proto2json_printer.h b/library/cpp/protobuf/json/proto2json_printer.h index 9dc5aa86c6..a127819386 100644 --- a/library/cpp/protobuf/json/proto2json_printer.h +++ b/library/cpp/protobuf/json/proto2json_printer.h @@ -39,7 +39,7 @@ namespace NProtobufJson { void PrintSingleField(const NProtoBuf::Message& proto, const NProtoBuf::FieldDescriptor& field, IJsonOutput& json, - TStringBuf key = {}); + TStringBuf key = {}, bool inProtoMap = false); void PrintKeyValue(const NProtoBuf::Message& proto, IJsonOutput& json); diff --git a/library/cpp/protobuf/json/ut/proto2json_ut.cpp b/library/cpp/protobuf/json/ut/proto2json_ut.cpp index f19558e60a..80dae6f01d 100644 --- a/library/cpp/protobuf/json/ut/proto2json_ut.cpp +++ b/library/cpp/protobuf/json/ut/proto2json_ut.cpp @@ -981,7 +981,7 @@ Y_UNIT_TEST(TestMapAsObject) { UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); } // TestMapAsObject -Y_UNIT_TEST(TestMapWTF) { +Y_UNIT_TEST(TestMapUsingGeneratedAsJSON) { TMapType proto; auto& items = *proto.MutableItems(); @@ -995,7 +995,47 @@ Y_UNIT_TEST(TestMapWTF) { UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr)); UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); -} // TestMapWTF +} // TestMapUsingGeneratedAsJSON + +Y_UNIT_TEST(TestMapDefaultValue) { + TMapType proto; + + auto& items = *proto.MutableItems(); + items["key1"] = ""; + + TString modelStr(R"_({"Items":{"key1":""}})_"); + + TStringStream jsonStr; + + TProto2JsonConfig config; + config.MapAsObject = true; + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); + UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); + + jsonStr.Clear(); + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr)); + UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); +} // TestMapDefaultValue + +Y_UNIT_TEST(TestMapDefaultMessageValue) { + TComplexMapType proto; + + auto& map = *proto.MutableNested(); + map["key1"]; // Creates an empty nested message + + TString modelStr(R"_({"Nested":{"key1":{}}})_"); + + TStringStream jsonStr; + + TProto2JsonConfig config; + config.MapAsObject = true; + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); + UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); + + jsonStr.Clear(); + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr)); + UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); +} // TestMapDefaultMessageValue Y_UNIT_TEST(TestStringifyNumbers) { #define TEST_SINGLE(flag, field, value, expectString) \ diff --git a/library/cpp/protobuf/json/ut/string_transform_ut.cpp b/library/cpp/protobuf/json/ut/string_transform_ut.cpp index a31dabcb0f..3a4df5c022 100644 --- a/library/cpp/protobuf/json/ut/string_transform_ut.cpp +++ b/library/cpp/protobuf/json/ut/string_transform_ut.cpp @@ -33,7 +33,6 @@ Y_UNIT_TEST_SUITE(TDoubleEscapeTransform) { TString s; s = "aba\\ca\"ba"; transform.Transform(s); - Cerr << "###" << s << Endl; UNIT_ASSERT_EQUAL(s, "aba\\\\\\\\ca\\\\\\\"ba"); } } @@ -52,7 +51,6 @@ Y_UNIT_TEST_SUITE(TDoubleUnescapeTransform) { TString s; s = "abacaba"; transform.Transform(s); - Cerr << "###" << s << Endl; UNIT_ASSERT_EQUAL("abacaba", s); } |