aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlavv17 <lavv17@yandex-team.com>2024-02-15 13:16:43 +0300
committerlavv17 <lavv17@yandex-team.com>2024-02-15 13:36:35 +0300
commit524319c9b011a50744ee1c873e7292b615052cd6 (patch)
treea7c52f035a4a86d558881e918a9526b37c405b8a
parentcbb28d478883b8acc82a4f6e3f816eae1da92887 (diff)
downloadydb-524319c9b011a50744ee1c873e7292b615052cd6.tar.gz
support Any in Proto2Json
31e18f04efdf8642428d4ab8ec8c87b4101f5ff2
-rw-r--r--library/cpp/protobuf/json/config.h8
-rw-r--r--library/cpp/protobuf/json/proto2json_printer.cpp51
-rw-r--r--library/cpp/protobuf/json/proto2json_printer.h3
-rw-r--r--library/cpp/protobuf/json/ut/proto2json_ut.cpp16
-rw-r--r--library/cpp/protobuf/json/ut/test.proto5
5 files changed, 79 insertions, 4 deletions
diff --git a/library/cpp/protobuf/json/config.h b/library/cpp/protobuf/json/config.h
index eee047e155..d17ac7b15b 100644
--- a/library/cpp/protobuf/json/config.h
+++ b/library/cpp/protobuf/json/config.h
@@ -95,6 +95,9 @@ namespace NProtobufJson {
};
EStringifyNumbersMode StringifyNumbers = StringifyLongNumbersNever;
+ /// Decode Any fields content
+ bool ConvertAny = false;
+
/// Custom field names generator.
TNameGenerator NameGenerator = {};
@@ -202,6 +205,11 @@ namespace NProtobufJson {
WriteNanAsString = value;
return *this;
}
+
+ TSelf& SetConvertAny(bool value) {
+ ConvertAny = value;
+ return *this;
+ }
};
}
diff --git a/library/cpp/protobuf/json/proto2json_printer.cpp b/library/cpp/protobuf/json/proto2json_printer.cpp
index b2426f395a..bf0f9eb60d 100644
--- a/library/cpp/protobuf/json/proto2json_printer.cpp
+++ b/library/cpp/protobuf/json/proto2json_printer.cpp
@@ -2,6 +2,8 @@
#include "config.h"
#include "util.h"
+#include <google/protobuf/any.pb.h>
+#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/util/time_util.h>
#include <library/cpp/protobuf/json/proto/enum_options.pb.h>
@@ -210,6 +212,39 @@ namespace NProtobufJson {
return false;
}
+ bool TProto2JsonPrinter::TryPrintAny(const Message& proto, IJsonOutput& json) {
+ using namespace google::protobuf;
+
+ const FieldDescriptor* typeUrlField;
+ const FieldDescriptor* valueField;
+ if (!Any::GetAnyFieldDescriptors(proto, &typeUrlField, &valueField)) {
+ return false;
+ }
+ const Reflection* const reflection = proto.GetReflection();
+ const TString& typeUrl = reflection->GetString(proto, typeUrlField);
+ TString fullTypeName;
+ if (!Any::ParseAnyTypeUrl(typeUrl, &fullTypeName)) {
+ return false;
+ }
+ const Descriptor* const valueDesc = proto.GetDescriptor()->file()->pool()->FindMessageTypeByName(fullTypeName);
+ if (!valueDesc) {
+ return false;
+ }
+ DynamicMessageFactory factory;
+ const THolder<Message> valueMessage{factory.GetPrototype(valueDesc)->New()};
+ const TString& serializedValue = reflection->GetString(proto, valueField);
+ if (!valueMessage->ParseFromString(serializedValue)) {
+ return false;
+ }
+
+ json.BeginObject();
+ json.WriteKey("@type").Write(typeUrl);
+ PrintFields(*valueMessage, json);
+ json.EndObject();
+
+ return true;
+ }
+
void TProto2JsonPrinter::PrintSingleField(const Message& proto,
const FieldDescriptor& field,
IJsonOutput& json,
@@ -267,7 +302,11 @@ namespace NProtobufJson {
if (Config.ConvertTimeAsString && HandleTimeConversion(reflection->GetMessage(proto, &field), json)) {
break;
}
- Print(reflection->GetMessage(proto, &field), json);
+ const Message& msg = reflection->GetMessage(proto, &field);
+ if (Config.ConvertAny && TryPrintAny(msg, json)) {
+ break;
+ }
+ Print(msg, json);
break;
}
@@ -487,12 +526,10 @@ namespace NProtobufJson {
PrintSingleField(proto, field, json, key);
}
- void TProto2JsonPrinter::Print(const Message& proto, IJsonOutput& json, bool closeMap) {
+ void TProto2JsonPrinter::PrintFields(const Message& proto, IJsonOutput& json) {
const Descriptor* descriptor = proto.GetDescriptor();
Y_ASSERT(descriptor);
- json.BeginObject();
-
// Iterate over all non-extension fields
for (int f = 0, endF = descriptor->field_count(); f < endF; ++f) {
const FieldDescriptor* field = descriptor->field(f);
@@ -518,6 +555,12 @@ namespace NProtobufJson {
}
}
}
+ }
+
+ void TProto2JsonPrinter::Print(const Message& proto, IJsonOutput& json, bool closeMap) {
+ json.BeginObject();
+
+ PrintFields(proto, json);
if (closeMap) {
json.EndObject();
diff --git a/library/cpp/protobuf/json/proto2json_printer.h b/library/cpp/protobuf/json/proto2json_printer.h
index a127819386..360e66ad2f 100644
--- a/library/cpp/protobuf/json/proto2json_printer.h
+++ b/library/cpp/protobuf/json/proto2json_printer.h
@@ -60,6 +60,9 @@ namespace NProtobufJson {
template <class T>
bool NeedStringifyNumber(T value) const;
+ bool TryPrintAny(const NProtoBuf::Message& proto, IJsonOutput& json);
+ void PrintFields(const NProtoBuf::Message& proto, IJsonOutput& json);
+
protected:
const TProto2JsonConfig& Config;
TString TmpBuf;
diff --git a/library/cpp/protobuf/json/ut/proto2json_ut.cpp b/library/cpp/protobuf/json/ut/proto2json_ut.cpp
index 80dae6f01d..9b74e73752 100644
--- a/library/cpp/protobuf/json/ut/proto2json_ut.cpp
+++ b/library/cpp/protobuf/json/ut/proto2json_ut.cpp
@@ -1143,4 +1143,20 @@ Y_UNIT_TEST(TestFloatToString) {
#undef TEST_SINGLE
} // TestFloatToString
+Y_UNIT_TEST(TestAny) {
+ TProto2JsonConfig config;
+ config.SetConvertAny(true);
+
+ TString modelStr(R"_({"Any":{"@type":"type.googleapis.com/NProtobufJsonTest.TFlatOptional","String":"value\""}})_");
+
+ TFlatOptional proto;
+ proto.SetString(R"_(value")_");
+ TContainsAny protoWithAny;
+ protoWithAny.MutableAny()->PackFrom(proto);
+
+ TStringStream jsonStr;
+ UNIT_ASSERT_NO_EXCEPTION(Proto2Json(protoWithAny, jsonStr, config));
+ UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr);
+}
+
} // TProto2JsonTest
diff --git a/library/cpp/protobuf/json/ut/test.proto b/library/cpp/protobuf/json/ut/test.proto
index 1f8487521b..0e40f1e469 100644
--- a/library/cpp/protobuf/json/ut/test.proto
+++ b/library/cpp/protobuf/json/ut/test.proto
@@ -1,5 +1,6 @@
package NProtobufJsonTest;
+import "google/protobuf/any.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/timestamp.proto";
@@ -230,3 +231,7 @@ message TCustomJsonEnumValue {
extend TExtensionField {
optional int32 bar = 123;
}
+
+message TContainsAny {
+ optional google.protobuf.Any Any = 1;
+}