aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/protobuf/json
diff options
context:
space:
mode:
authorAlexSm <alex@ydb.tech>2023-12-22 20:30:08 +0100
committerGitHub <noreply@github.com>2023-12-22 20:30:08 +0100
commit6b4f46a6883f21c16eef367106167ea59932515e (patch)
tree5833709b16bba3948f15e88b9038229c5065605b /library/cpp/protobuf/json
parenta8b737f2a6df02f6e45ed703246c75f0f4cf7a34 (diff)
downloadydb-6b4f46a6883f21c16eef367106167ea59932515e.tar.gz
Import libs 3 (#679)
Diffstat (limited to 'library/cpp/protobuf/json')
-rw-r--r--library/cpp/protobuf/json/json_writer_output.h5
-rw-r--r--library/cpp/protobuf/json/proto2json_printer.cpp10
-rw-r--r--library/cpp/protobuf/json/proto2json_printer.h2
-rw-r--r--library/cpp/protobuf/json/ut/proto2json_ut.cpp44
-rw-r--r--library/cpp/protobuf/json/ut/string_transform_ut.cpp2
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);
}