aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/protobuf/json
diff options
context:
space:
mode:
authortimuratshin <timuratshin@yandex-team.com>2025-06-17 11:39:01 +0300
committertimuratshin <timuratshin@yandex-team.com>2025-06-17 12:07:27 +0300
commit280fed21e0058de0be049996f68b10a336b69370 (patch)
treee52d71481779eee394217fe9d67eb5326c6da071 /library/cpp/protobuf/json
parentde699c5726b134d10b3311deb0628fc74e82e877 (diff)
downloadydb-280fed21e0058de0be049996f68b10a336b69370.tar.gz
Support google::protobuf::Struct and google::protobuf::Value in Json2Proto
Добавляем поддержку парсинга TJsonValue в google::protobuf::Struct и google::protobuf::Value Сериализация в пути… commit_hash:0815499b09ba8eeaf77dbda5ab5aced91f1e2474
Diffstat (limited to 'library/cpp/protobuf/json')
-rw-r--r--library/cpp/protobuf/json/json2proto.cpp53
-rw-r--r--library/cpp/protobuf/json/ut/json2proto_ut.cpp79
2 files changed, 132 insertions, 0 deletions
diff --git a/library/cpp/protobuf/json/json2proto.cpp b/library/cpp/protobuf/json/json2proto.cpp
index 823c471b967..a1d7e862ef0 100644
--- a/library/cpp/protobuf/json/json2proto.cpp
+++ b/library/cpp/protobuf/json/json2proto.cpp
@@ -7,6 +7,8 @@
#include <google/protobuf/util/time_util.h>
#include <google/protobuf/message.h>
#include <google/protobuf/descriptor.h>
+#include <google/protobuf/struct.pb.h>
+
#include <util/generic/hash.h>
#include <util/generic/maybe.h>
@@ -517,6 +519,57 @@ namespace NProtobufJson {
const google::protobuf::Descriptor* descriptor = proto.GetDescriptor();
Y_ASSERT(!!descriptor);
+
+ if (descriptor->well_known_type() == google::protobuf::Descriptor::WELLKNOWNTYPE_STRUCT) {
+ Y_ENSURE(json.IsMap(), "Failed to merge json to proto for message: " << descriptor->full_name() << ", expected json map.");
+ google::protobuf::Struct msg;
+ for (const auto& [key, value] : json.GetMap()) {
+ google::protobuf::Value valueMsg;
+ MergeJson2Proto(value, valueMsg, config);
+ (*msg.mutable_fields())[key] = std::move(valueMsg);
+ }
+ proto.GetReflection()->Swap(&proto, &msg);
+ return;
+ } else if (descriptor->well_known_type() == google::protobuf::Descriptor::WELLKNOWNTYPE_VALUE) {
+ google::protobuf::Value msg;
+ switch (json.GetType()) {
+ case NJson::JSON_UNDEFINED:
+ break;
+ case NJson::JSON_NULL:
+ msg.set_null_value({});
+ break;
+ case NJson::JSON_BOOLEAN:
+ msg.set_bool_value(json.GetBoolean());
+ break;
+ case NJson::JSON_INTEGER:
+ case NJson::JSON_DOUBLE:
+ case NJson::JSON_UINTEGER:
+ msg.set_number_value(json.GetDouble());
+ break;
+ case NJson::JSON_STRING:
+ msg.set_string_value(json.GetString());
+ break;
+ case NJson::JSON_MAP:
+ {
+ auto* structValue = msg.mutable_struct_value();
+ MergeJson2Proto(json, *structValue, config);
+ break;
+ }
+ case NJson::JSON_ARRAY:
+ {
+ auto* arrayValue = msg.mutable_list_value();
+ const auto& jsonArray = json.GetArray();
+ arrayValue->mutable_values()->Reserve(jsonArray.size());
+ for (const auto& item : jsonArray) {
+ MergeJson2Proto(item, *arrayValue->add_values(), config);
+ }
+ break;
+ }
+ }
+
+ proto.GetReflection()->Swap(&proto, &msg);
+ return;
+ }
Y_ENSURE(json.IsMap(), "Failed to merge json to proto for message: " << descriptor->full_name() << ", expected json map.");
for (int f = 0, endF = descriptor->field_count(); f < endF; ++f) {
diff --git a/library/cpp/protobuf/json/ut/json2proto_ut.cpp b/library/cpp/protobuf/json/ut/json2proto_ut.cpp
index 7b3e829868e..1172b2b8db6 100644
--- a/library/cpp/protobuf/json/ut/json2proto_ut.cpp
+++ b/library/cpp/protobuf/json/ut/json2proto_ut.cpp
@@ -2,6 +2,8 @@
#include "proto.h"
#include "proto2json.h"
+#include <google/protobuf/struct.pb.h>
+
#include <library/cpp/protobuf/json/ut/test.pb.h>
#include <library/cpp/json/json_value.h>
@@ -1186,4 +1188,81 @@ Y_UNIT_TEST(TestSimplifiedTimestamp) {
UNIT_ASSERT_EQUAL(NProtoInterop::CastFromProto(simpleTimestamp.GetTimestamp()), TInstant::ParseIso8601("2014-08-26T15:52:15Z"));
} // TestSimplifiedTimestamp
+Y_UNIT_TEST(TestValue) {
+ {
+ NJson::TJsonValue json = 100.0;
+ google::protobuf::Value value;
+ NProtobufJson::Json2Proto(json, value);
+ UNIT_ASSERT(value.has_number_value());
+ UNIT_ASSERT_EQUAL(value.number_value(), 100.0);
+ }
+ {
+ NJson::TJsonValue json = 100LL;
+ google::protobuf::Value value;
+ NProtobufJson::Json2Proto(json, value);
+ UNIT_ASSERT(value.has_number_value());
+ UNIT_ASSERT_EQUAL(value.number_value(), 100.0);
+ }
+ {
+ NJson::TJsonValue json = 100ULL;
+ google::protobuf::Value value;
+ NProtobufJson::Json2Proto(json, value);
+ UNIT_ASSERT(value.has_number_value());
+ UNIT_ASSERT_EQUAL(value.number_value(), 100.0);
+ }
+ {
+ NJson::TJsonValue json = "TestString";
+ google::protobuf::Value value;
+ NProtobufJson::Json2Proto(json, value);
+ UNIT_ASSERT(value.has_string_value());
+ UNIT_ASSERT_EQUAL(value.string_value(), "TestString");
+ }
+ {
+ NJson::TJsonValue json;
+ json.AppendValue("TestString");
+ json.AppendValue(2);
+ google::protobuf::Value value;
+ NProtobufJson::Json2Proto(json, value);
+ UNIT_ASSERT(value.has_list_value());
+ const auto& list = value.list_value().values();
+ UNIT_ASSERT_EQUAL(list.size(), 2);
+ UNIT_ASSERT(list.Get(0).has_string_value());
+ UNIT_ASSERT_EQUAL(list.Get(0).string_value(), "TestString");
+ UNIT_ASSERT(list.Get(1).has_number_value());
+ UNIT_ASSERT_EQUAL(list.Get(1).number_value(), 2.0);
+ }
+ {
+ NJson::TJsonValue json;
+ json["str"] = "TestString";
+ json["int"] = 2;
+ google::protobuf::Value value;
+ NProtobufJson::Json2Proto(json, value);
+ UNIT_ASSERT(value.has_struct_value());
+ const auto& fields = value.struct_value().fields();
+ UNIT_ASSERT_EQUAL(fields.size(), 2);
+
+ UNIT_ASSERT(fields.at("str").has_string_value());
+ UNIT_ASSERT_EQUAL(fields.at("str").string_value(), "TestString");
+
+ UNIT_ASSERT(fields.at("int").has_number_value());
+ UNIT_ASSERT_EQUAL(fields.at("int").number_value(), 2.0);
+ }
+} // TestValue
+
+Y_UNIT_TEST(TestStruct) {
+ NJson::TJsonValue json;
+ json["str"] = "TestString";
+ json["int"] = 2;
+ google::protobuf::Struct structProto;
+ NProtobufJson::Json2Proto(json, structProto);
+
+ const auto& fields = structProto.fields();
+ UNIT_ASSERT_EQUAL(fields.size(), 2);
+ UNIT_ASSERT(fields.at("str").has_string_value());
+ UNIT_ASSERT_EQUAL(fields.at("str").string_value(), "TestString");
+
+ UNIT_ASSERT(fields.at("int").has_number_value());
+ UNIT_ASSERT_EQUAL(fields.at("int").number_value(), 2.0);
+} // TestStruct
+
} // TJson2ProtoTest