Skip to content

Commit 419fb5c

Browse files
LOGBROKER-8891: fix inability to parse json into protobuf map in http_proxy
1 parent 9e4a92a commit 419fb5c

File tree

3 files changed

+46
-16
lines changed

3 files changed

+46
-16
lines changed

ydb/core/http_proxy/json_proto_conversion.h

+35-16
Original file line numberDiff line numberDiff line change
@@ -147,59 +147,78 @@ inline void AddJsonObjectToProtoAsMap(
147147
const google::protobuf::Reflection* reflection,
148148
grpc::protobuf::Message* message,
149149
const JSON& jsonObject,
150+
ui32 depth,
150151
std::function<const MAP(const JSON&)> extractMap,
151-
std::function<const TString(const JSON&)> valueToString
152+
std::function<const TString(const JSON&)> valueToString,
153+
std::function<void(const JSON&, grpc::protobuf::Message*, ui32)> jsonObjectToMessage
152154
) {
153155
const auto& protoMap = reflection->GetMutableRepeatedFieldRef<google::protobuf::Message>(message, fieldDescriptor);
154156
for (const auto& [key, value] : extractMap(jsonObject)) {
155-
std::unique_ptr<google::protobuf::Message> stringStringEntry(
157+
std::unique_ptr<google::protobuf::Message> mapEntry(
156158
google::protobuf::MessageFactory::generated_factory()
157159
->GetPrototype(fieldDescriptor->message_type())
158160
->New(message->GetArena())
159161
);
160-
stringStringEntry
162+
mapEntry
161163
->GetReflection()
162-
->SetString(stringStringEntry.get(), fieldDescriptor->message_type()->field(0), key);
163-
stringStringEntry
164-
->GetReflection()
165-
->SetString(stringStringEntry.get(), fieldDescriptor->message_type()->field(1), valueToString(value));
166-
protoMap.Add(*stringStringEntry);
164+
->SetString(mapEntry.get(), fieldDescriptor->message_type()->field(0), key);
165+
166+
auto valueField = fieldDescriptor->message_type()->field(1);
167+
if (valueField->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
168+
auto *msg = mapEntry->GetReflection()->MutableMessage(mapEntry.get(), valueField);
169+
jsonObjectToMessage(value, msg, depth);
170+
} else if (valueField->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_STRING) {
171+
mapEntry->GetReflection()->SetString(mapEntry.get(), valueField, valueToString(value));
172+
} else {
173+
throw NKikimr::NSQS::TSQSException(NKikimr::NSQS::NErrors::INVALID_PARAMETER_VALUE)
174+
<< "Only String and Object can be converted to protobuf map";
175+
}
176+
protoMap.Add(std::move(*mapEntry));
167177
}
168178
}
169179

180+
void JsonToProto(const NJson::TJsonValue& jsonValue, NProtoBuf::Message* message, ui32 depth = 0);
181+
170182
inline void AddJsonObjectToProtoAsMap(
171183
const google::protobuf::FieldDescriptor* fieldDescriptor,
172184
const google::protobuf::Reflection* reflection,
173185
grpc::protobuf::Message* message,
174-
const NJson::TJsonValue& jsonObject
186+
const NJson::TJsonValue& jsonObject,
187+
ui32 depth
175188
) {
176189
AddJsonObjectToProtoAsMap<NJson::TJsonValue, NJson::TJsonValue::TMapType>(
177190
fieldDescriptor,
178191
reflection,
179192
message,
180193
jsonObject,
194+
depth,
181195
[](auto& json) { return json.GetMap(); },
182-
[](auto& value) -> const TString { return value.GetString(); }
196+
[](auto& value) -> const TString { return value.GetString(); },
197+
[](auto& json, auto message, auto depth) { JsonToProto(json, message, depth); }
183198
);
184199
}
200+
void NlohmannJsonToProto(const nlohmann::json& jsonValue, NProtoBuf::Message* message, ui32 depth = 0);
185201

186202
inline void AddJsonObjectToProtoAsMap(
187203
const google::protobuf::FieldDescriptor* fieldDescriptor,
188204
const google::protobuf::Reflection* reflection,
189205
grpc::protobuf::Message* message,
190-
const nlohmann::basic_json<>& jsonObject
206+
const nlohmann::basic_json<>& jsonObject,
207+
ui32 depth
191208
) {
192209
AddJsonObjectToProtoAsMap<nlohmann::basic_json<>, std::map<TString, nlohmann::basic_json<>>>(
193210
fieldDescriptor,
194211
reflection,
195212
message,
196213
jsonObject,
214+
depth,
197215
[](auto& json) { return json.template get<std::map<TString, nlohmann::basic_json<>>>(); },
198-
[](auto& value) -> const TString { return value.template get<TString>(); }
216+
[](auto& value) -> const TString { return value.template get<TString>(); },
217+
[](auto& json, auto message, auto depth) { NlohmannJsonToProto(json, message, depth); }
199218
);
200219
}
201220

202-
inline void JsonToProto(const NJson::TJsonValue& jsonValue, NProtoBuf::Message* message, ui32 depth = 0) {
221+
inline void JsonToProto(const NJson::TJsonValue& jsonValue, NProtoBuf::Message* message, ui32 depth) {
203222
Y_ENSURE(depth < 101, "Json depth is > 100");
204223
Y_ENSURE_EX(
205224
!jsonValue.IsNull(),
@@ -348,7 +367,7 @@ inline void JsonToProto(const NJson::TJsonValue& jsonValue, NProtoBuf::Message*
348367
break;
349368
case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: {
350369
if (fieldDescriptor->is_map()) {
351-
AddJsonObjectToProtoAsMap(fieldDescriptor, reflection, message, value);
370+
AddJsonObjectToProtoAsMap(fieldDescriptor, reflection, message, value, depth);
352371
} else {
353372
auto *msg = reflection->MutableMessage(message, fieldDescriptor);
354373
JsonToProto(value, msg, depth + 1);
@@ -366,7 +385,7 @@ inline void JsonToProto(const NJson::TJsonValue& jsonValue, NProtoBuf::Message*
366385
}
367386
}
368387

369-
inline void NlohmannJsonToProto(const nlohmann::json& jsonValue, NProtoBuf::Message* message, ui32 depth = 0) {
388+
inline void NlohmannJsonToProto(const nlohmann::json& jsonValue, NProtoBuf::Message* message, ui32 depth) {
370389
Y_ENSURE(depth < 101, "Json depth is > 100");
371390
Y_ENSURE_EX(
372391
!jsonValue.is_null(),
@@ -518,7 +537,7 @@ inline void NlohmannJsonToProto(const nlohmann::json& jsonValue, NProtoBuf::Mess
518537
break;
519538
case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: {
520539
if (fieldDescriptor->is_map()) {
521-
AddJsonObjectToProtoAsMap(fieldDescriptor, reflection, message, value);
540+
AddJsonObjectToProtoAsMap(fieldDescriptor, reflection, message, value, depth);
522541
} else {
523542
auto *msg = reflection->MutableMessage(message, fieldDescriptor);
524543
NlohmannJsonToProto(value, msg, depth + 1);

ydb/core/http_proxy/ut/http_proxy_ut.h

+10
Original file line numberDiff line numberDiff line change
@@ -1886,6 +1886,15 @@ Y_UNIT_TEST_SUITE(TestHttpProxy) {
18861886
message0["MessageBody"] = "MessageBody-0";
18871887
message0["MessageDeduplicationId"] = "MessageDeduplicationId-0";
18881888

1889+
NJson::TJsonValue delaySeconds;
1890+
delaySeconds["StringValue"] = "1";
1891+
delaySeconds["DataType"] = "String";
1892+
1893+
NJson::TJsonValue attributes;
1894+
attributes["DelaySeconds"] = delaySeconds;
1895+
1896+
message0["MessageAttributes"] = attributes;
1897+
18891898
NJson::TJsonValue message1;
18901899
message1["Id"] = "Id-1";
18911900
message1["MessageBody"] = "MessageBody-1";
@@ -1903,6 +1912,7 @@ Y_UNIT_TEST_SUITE(TestHttpProxy) {
19031912
UNIT_ASSERT(json["Successful"].GetArray().size() == 2);
19041913
auto succesful0 = json["Successful"][0];
19051914
UNIT_ASSERT(succesful0["Id"] == "Id-0");
1915+
UNIT_ASSERT(!GetByPath<TString>(succesful0, "Md5OfMessageAttributes").empty());
19061916
UNIT_ASSERT(!GetByPath<TString>(succesful0, "Md5OfMessageBody").empty());
19071917
UNIT_ASSERT(!GetByPath<TString>(succesful0, "MessageId").empty());
19081918
}

ydb/services/ymq/ymq_proxy.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,7 @@ namespace NKikimr::NYmq::V1 {
764764
} else {
765765
auto currentSuccessful = result.Addsuccessful();
766766
currentSuccessful->Setid(entry.GetId());
767+
currentSuccessful->Setmd5_of_message_attributes(entry.GetMD5OfMessageAttributes());
767768
currentSuccessful->Setmd5_of_message_body(entry.GetMD5OfMessageBody());
768769
currentSuccessful->Setmessage_id(entry.GetMessageId());
769770
currentSuccessful->Setsequence_number(std::to_string(entry.GetSequenceNumber()));

0 commit comments

Comments
 (0)