diff options
author | v01d <v01d@yandex-team.ru> | 2022-02-10 16:49:40 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:49:40 +0300 |
commit | 5c6482e8c13dfaad60e604f0474606a0ec153b1d (patch) | |
tree | 5d5cb817648f650d76cf1076100726fd9b8448e8 /library/cpp/protobuf/json/proto2json_printer.cpp | |
parent | fa8b0420162dd36d4f569fdc3f63da0bef8bb8c7 (diff) | |
download | ydb-5c6482e8c13dfaad60e604f0474606a0ec153b1d.tar.gz |
Restoring authorship annotation for <v01d@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'library/cpp/protobuf/json/proto2json_printer.cpp')
-rw-r--r-- | library/cpp/protobuf/json/proto2json_printer.cpp | 742 |
1 files changed, 371 insertions, 371 deletions
diff --git a/library/cpp/protobuf/json/proto2json_printer.cpp b/library/cpp/protobuf/json/proto2json_printer.cpp index e165853f0a..6123eab0f2 100644 --- a/library/cpp/protobuf/json/proto2json_printer.cpp +++ b/library/cpp/protobuf/json/proto2json_printer.cpp @@ -1,195 +1,195 @@ #include "proto2json_printer.h" #include "config.h" -#include "util.h" +#include "util.h" #include <util/generic/yexception.h> #include <util/string/ascii.h> -#include <util/string/cast.h> +#include <util/string/cast.h> namespace NProtobufJson { - using namespace NProtoBuf; + using namespace NProtoBuf; - class TJsonKeyBuilder { - public: - TJsonKeyBuilder(const FieldDescriptor& field, const TProto2JsonConfig& config, TString& tmpBuf) - : NewKeyStr(tmpBuf) - { + class TJsonKeyBuilder { + public: + TJsonKeyBuilder(const FieldDescriptor& field, const TProto2JsonConfig& config, TString& tmpBuf) + : NewKeyStr(tmpBuf) + { if (config.NameGenerator) { NewKeyStr = config.NameGenerator(field); NewKeyBuf = NewKeyStr; return; } - if (config.UseJsonName) { - Y_ASSERT(!field.json_name().empty()); + if (config.UseJsonName) { + Y_ASSERT(!field.json_name().empty()); NewKeyStr = field.json_name(); if (!field.has_json_name() && !NewKeyStr.empty()) { // FIXME: https://st.yandex-team.ru/CONTRIB-139 NewKeyStr[0] = AsciiToLower(NewKeyStr[0]); } NewKeyBuf = NewKeyStr; - return; - } - - switch (config.FieldNameMode) { - case TProto2JsonConfig::FieldNameOriginalCase: { - NewKeyBuf = field.name(); - break; - } - - case TProto2JsonConfig::FieldNameLowerCase: { - NewKeyStr = field.name(); - NewKeyStr.to_lower(); - NewKeyBuf = NewKeyStr; - break; - } - - case TProto2JsonConfig::FieldNameUpperCase: { - NewKeyStr = field.name(); - NewKeyStr.to_upper(); - NewKeyBuf = NewKeyStr; - break; - } - - case TProto2JsonConfig::FieldNameCamelCase: { - NewKeyStr = field.name(); + return; + } + + switch (config.FieldNameMode) { + case TProto2JsonConfig::FieldNameOriginalCase: { + NewKeyBuf = field.name(); + break; + } + + case TProto2JsonConfig::FieldNameLowerCase: { + NewKeyStr = field.name(); + NewKeyStr.to_lower(); + NewKeyBuf = NewKeyStr; + break; + } + + case TProto2JsonConfig::FieldNameUpperCase: { + NewKeyStr = field.name(); + NewKeyStr.to_upper(); + NewKeyBuf = NewKeyStr; + break; + } + + case TProto2JsonConfig::FieldNameCamelCase: { + NewKeyStr = field.name(); if (!NewKeyStr.empty()) { - NewKeyStr[0] = AsciiToLower(NewKeyStr[0]); - } - NewKeyBuf = NewKeyStr; - break; - } - - case TProto2JsonConfig::FieldNameSnakeCase: { - NewKeyStr = field.name(); - ToSnakeCase(&NewKeyStr); - NewKeyBuf = NewKeyStr; - break; - } - - case TProto2JsonConfig::FieldNameSnakeCaseDense: { - NewKeyStr = field.name(); - ToSnakeCaseDense(&NewKeyStr); - NewKeyBuf = NewKeyStr; - break; - } - - default: - Y_VERIFY_DEBUG(false, "Unknown FieldNameMode."); + NewKeyStr[0] = AsciiToLower(NewKeyStr[0]); + } + NewKeyBuf = NewKeyStr; + break; + } + + case TProto2JsonConfig::FieldNameSnakeCase: { + NewKeyStr = field.name(); + ToSnakeCase(&NewKeyStr); + NewKeyBuf = NewKeyStr; + break; + } + + case TProto2JsonConfig::FieldNameSnakeCaseDense: { + NewKeyStr = field.name(); + ToSnakeCaseDense(&NewKeyStr); + NewKeyBuf = NewKeyStr; + break; + } + + default: + Y_VERIFY_DEBUG(false, "Unknown FieldNameMode."); } } - const TStringBuf& GetKey() const { - return NewKeyBuf; + const TStringBuf& GetKey() const { + return NewKeyBuf; } - - private: - TStringBuf NewKeyBuf; - TString& NewKeyStr; - }; - - TProto2JsonPrinter::TProto2JsonPrinter(const TProto2JsonConfig& cfg) - : Config(cfg) - { + + private: + TStringBuf NewKeyBuf; + TString& NewKeyStr; + }; + + TProto2JsonPrinter::TProto2JsonPrinter(const TProto2JsonConfig& cfg) + : Config(cfg) + { + } + + TProto2JsonPrinter::~TProto2JsonPrinter() { + } + + TStringBuf TProto2JsonPrinter::MakeKey(const FieldDescriptor& field) { + return TJsonKeyBuilder(field, GetConfig(), TmpBuf).GetKey(); + } + + template <bool InMapContext, typename T> + std::enable_if_t<InMapContext, void> WriteWithMaybeEmptyKey(IJsonOutput& json, const TStringBuf& key, const T& value) { + json.WriteKey(key).Write(value); } - TProto2JsonPrinter::~TProto2JsonPrinter() { + template <bool InMapContext, typename T> + std::enable_if_t<!InMapContext, void> WriteWithMaybeEmptyKey(IJsonOutput& array, const TStringBuf& key, const T& value) { + Y_ASSERT(!key); + array.Write(value); } - TStringBuf TProto2JsonPrinter::MakeKey(const FieldDescriptor& field) { - return TJsonKeyBuilder(field, GetConfig(), TmpBuf).GetKey(); - } - - template <bool InMapContext, typename T> - std::enable_if_t<InMapContext, void> WriteWithMaybeEmptyKey(IJsonOutput& json, const TStringBuf& key, const T& value) { - json.WriteKey(key).Write(value); - } - - template <bool InMapContext, typename T> - std::enable_if_t<!InMapContext, void> WriteWithMaybeEmptyKey(IJsonOutput& array, const TStringBuf& key, const T& value) { - Y_ASSERT(!key); - array.Write(value); - } - - template <bool InMapContext> - void TProto2JsonPrinter::PrintStringValue(const FieldDescriptor& field, - const TStringBuf& key, const TString& value, - IJsonOutput& json) { - if (!GetConfig().StringTransforms.empty()) { - TString tmpBuf = value; - for (const TStringTransformPtr& stringTransform : GetConfig().StringTransforms) { - Y_ASSERT(stringTransform); - if (stringTransform) { - if (field.type() == FieldDescriptor::TYPE_BYTES) - stringTransform->TransformBytes(tmpBuf); - else - stringTransform->Transform(tmpBuf); - } - } - WriteWithMaybeEmptyKey<InMapContext>(json, key, tmpBuf); - } else { - WriteWithMaybeEmptyKey<InMapContext>(json, key, value); - } - } - - template <bool InMapContext> - void TProto2JsonPrinter::PrintEnumValue(const TStringBuf& key, - const EnumValueDescriptor* value, - IJsonOutput& json) { + template <bool InMapContext> + void TProto2JsonPrinter::PrintStringValue(const FieldDescriptor& field, + const TStringBuf& key, const TString& value, + IJsonOutput& json) { + if (!GetConfig().StringTransforms.empty()) { + TString tmpBuf = value; + for (const TStringTransformPtr& stringTransform : GetConfig().StringTransforms) { + Y_ASSERT(stringTransform); + if (stringTransform) { + if (field.type() == FieldDescriptor::TYPE_BYTES) + stringTransform->TransformBytes(tmpBuf); + else + stringTransform->Transform(tmpBuf); + } + } + WriteWithMaybeEmptyKey<InMapContext>(json, key, tmpBuf); + } else { + WriteWithMaybeEmptyKey<InMapContext>(json, key, value); + } + } + + template <bool InMapContext> + void TProto2JsonPrinter::PrintEnumValue(const TStringBuf& key, + const EnumValueDescriptor* value, + IJsonOutput& json) { if (Config.EnumValueGenerator) { WriteWithMaybeEmptyKey<InMapContext>(json, key, Config.EnumValueGenerator(*value)); return; } - switch (GetConfig().EnumMode) { - case TProto2JsonConfig::EnumNumber: { - WriteWithMaybeEmptyKey<InMapContext>(json, key, value->number()); - break; - } + switch (GetConfig().EnumMode) { + case TProto2JsonConfig::EnumNumber: { + WriteWithMaybeEmptyKey<InMapContext>(json, key, value->number()); + break; + } - case TProto2JsonConfig::EnumName: { - WriteWithMaybeEmptyKey<InMapContext>(json, key, value->name()); - break; - } + case TProto2JsonConfig::EnumName: { + WriteWithMaybeEmptyKey<InMapContext>(json, key, value->name()); + break; + } - case TProto2JsonConfig::EnumFullName: { - WriteWithMaybeEmptyKey<InMapContext>(json, key, value->full_name()); - break; + case TProto2JsonConfig::EnumFullName: { + WriteWithMaybeEmptyKey<InMapContext>(json, key, value->full_name()); + break; } - case TProto2JsonConfig::EnumNameLowerCase: { - TString newName = value->name(); - newName.to_lower(); - WriteWithMaybeEmptyKey<InMapContext>(json, key, newName); - break; - } - - case TProto2JsonConfig::EnumFullNameLowerCase: { - TString newName = value->full_name(); - newName.to_lower(); - WriteWithMaybeEmptyKey<InMapContext>(json, key, newName); - break; - } - - default: - Y_VERIFY_DEBUG(false, "Unknown EnumMode."); - } + case TProto2JsonConfig::EnumNameLowerCase: { + TString newName = value->name(); + newName.to_lower(); + WriteWithMaybeEmptyKey<InMapContext>(json, key, newName); + break; + } + + case TProto2JsonConfig::EnumFullNameLowerCase: { + TString newName = value->full_name(); + newName.to_lower(); + WriteWithMaybeEmptyKey<InMapContext>(json, key, newName); + break; + } + + default: + Y_VERIFY_DEBUG(false, "Unknown EnumMode."); + } } - void TProto2JsonPrinter::PrintSingleField(const Message& proto, - const FieldDescriptor& field, - IJsonOutput& json, - TStringBuf key) { - Y_VERIFY(!field.is_repeated(), "field is repeated."); + void TProto2JsonPrinter::PrintSingleField(const Message& proto, + const FieldDescriptor& field, + IJsonOutput& json, + TStringBuf key) { + Y_VERIFY(!field.is_repeated(), "field is repeated."); - if (!key) { - key = MakeKey(field); - } + if (!key) { + key = MakeKey(field); + } -#define FIELD_TO_JSON(EProtoCppType, ProtoGet) \ - case FieldDescriptor::EProtoCppType: { \ - json.WriteKey(key).Write(reflection->ProtoGet(proto, &field)); \ - break; \ +#define FIELD_TO_JSON(EProtoCppType, ProtoGet) \ + case FieldDescriptor::EProtoCppType: { \ + json.WriteKey(key).Write(reflection->ProtoGet(proto, &field)); \ + break; \ } #define INT_FIELD_TO_JSON(EProtoCppType, ProtoGet) \ @@ -203,7 +203,7 @@ namespace NProtobufJson { break; \ } - const Reflection* reflection = proto.GetReflection(); + const Reflection* reflection = proto.GetReflection(); bool shouldPrintField = reflection->HasField(proto, &field); if (!shouldPrintField && GetConfig().MissingSingleKeyMode == TProto2JsonConfig::MissingKeyExplicitDefaultThrowRequired) { @@ -217,251 +217,251 @@ namespace NProtobufJson { shouldPrintField = shouldPrintField || GetConfig().MissingSingleKeyMode == TProto2JsonConfig::MissingKeyDefault; if (shouldPrintField) { - switch (field.cpp_type()) { + switch (field.cpp_type()) { INT_FIELD_TO_JSON(CPPTYPE_INT32, GetInt32); INT_FIELD_TO_JSON(CPPTYPE_INT64, GetInt64); INT_FIELD_TO_JSON(CPPTYPE_UINT32, GetUInt32); INT_FIELD_TO_JSON(CPPTYPE_UINT64, GetUInt64); - FIELD_TO_JSON(CPPTYPE_DOUBLE, GetDouble); - FIELD_TO_JSON(CPPTYPE_FLOAT, GetFloat); - FIELD_TO_JSON(CPPTYPE_BOOL, GetBool); - - case FieldDescriptor::CPPTYPE_MESSAGE: { - json.WriteKey(key); - Print(reflection->GetMessage(proto, &field), json); - break; - } - - case FieldDescriptor::CPPTYPE_ENUM: { - PrintEnumValue<true>(key, reflection->GetEnum(proto, &field), json); - break; - } - - case FieldDescriptor::CPPTYPE_STRING: { - TString scratch; - const TString& value = reflection->GetStringReference(proto, &field, &scratch); - PrintStringValue<true>(field, key, value, json); - break; - } - - default: - ythrow yexception() << "Unknown protobuf field type: " - << static_cast<int>(field.cpp_type()) << "."; - } - } else { - switch (GetConfig().MissingSingleKeyMode) { - case TProto2JsonConfig::MissingKeyNull: { - json.WriteKey(key).WriteNull(); - break; - } - - case TProto2JsonConfig::MissingKeySkip: + FIELD_TO_JSON(CPPTYPE_DOUBLE, GetDouble); + FIELD_TO_JSON(CPPTYPE_FLOAT, GetFloat); + FIELD_TO_JSON(CPPTYPE_BOOL, GetBool); + + case FieldDescriptor::CPPTYPE_MESSAGE: { + json.WriteKey(key); + Print(reflection->GetMessage(proto, &field), json); + break; + } + + case FieldDescriptor::CPPTYPE_ENUM: { + PrintEnumValue<true>(key, reflection->GetEnum(proto, &field), json); + break; + } + + case FieldDescriptor::CPPTYPE_STRING: { + TString scratch; + const TString& value = reflection->GetStringReference(proto, &field, &scratch); + PrintStringValue<true>(field, key, value, json); + break; + } + + default: + ythrow yexception() << "Unknown protobuf field type: " + << static_cast<int>(field.cpp_type()) << "."; + } + } else { + switch (GetConfig().MissingSingleKeyMode) { + case TProto2JsonConfig::MissingKeyNull: { + json.WriteKey(key).WriteNull(); + break; + } + + case TProto2JsonConfig::MissingKeySkip: case TProto2JsonConfig::MissingKeyExplicitDefaultThrowRequired: - default: - break; - } + default: + break; + } } -#undef FIELD_TO_JSON - } - - void TProto2JsonPrinter::PrintRepeatedField(const Message& proto, - const FieldDescriptor& field, - IJsonOutput& json, - TStringBuf key) { - Y_VERIFY(field.is_repeated(), "field isn't repeated."); - - const bool isMap = field.is_map() && GetConfig().MapAsObject; - if (!key) { - key = MakeKey(field); +#undef FIELD_TO_JSON + } + + void TProto2JsonPrinter::PrintRepeatedField(const Message& proto, + const FieldDescriptor& field, + IJsonOutput& json, + TStringBuf key) { + Y_VERIFY(field.is_repeated(), "field isn't repeated."); + + const bool isMap = field.is_map() && GetConfig().MapAsObject; + if (!key) { + key = MakeKey(field); } -#define REPEATED_FIELD_TO_JSON(EProtoCppType, ProtoGet) \ - case FieldDescriptor::EProtoCppType: { \ +#define REPEATED_FIELD_TO_JSON(EProtoCppType, ProtoGet) \ + case FieldDescriptor::EProtoCppType: { \ for (size_t i = 0, endI = reflection->FieldSize(proto, &field); i < endI; ++i) \ - json.Write(reflection->ProtoGet(proto, &field, i)); \ - break; \ + json.Write(reflection->ProtoGet(proto, &field, i)); \ + break; \ } - const Reflection* reflection = proto.GetReflection(); - - if (reflection->FieldSize(proto, &field) > 0) { - json.WriteKey(key); - if (isMap) { - json.BeginObject(); - } else { - json.BeginList(); - } - - switch (field.cpp_type()) { - REPEATED_FIELD_TO_JSON(CPPTYPE_INT32, GetRepeatedInt32); - REPEATED_FIELD_TO_JSON(CPPTYPE_INT64, GetRepeatedInt64); - REPEATED_FIELD_TO_JSON(CPPTYPE_UINT32, GetRepeatedUInt32); - REPEATED_FIELD_TO_JSON(CPPTYPE_UINT64, GetRepeatedUInt64); - REPEATED_FIELD_TO_JSON(CPPTYPE_DOUBLE, GetRepeatedDouble); - REPEATED_FIELD_TO_JSON(CPPTYPE_FLOAT, GetRepeatedFloat); - REPEATED_FIELD_TO_JSON(CPPTYPE_BOOL, GetRepeatedBool); - - case FieldDescriptor::CPPTYPE_MESSAGE: { - if (isMap) { - for (size_t i = 0, endI = reflection->FieldSize(proto, &field); i < endI; ++i) { - PrintKeyValue(reflection->GetRepeatedMessage(proto, &field, i), json); - } - } else { - for (size_t i = 0, endI = reflection->FieldSize(proto, &field); i < endI; ++i) { - Print(reflection->GetRepeatedMessage(proto, &field, i), json); - } - } - break; - } - - case FieldDescriptor::CPPTYPE_ENUM: { - for (int i = 0, endI = reflection->FieldSize(proto, &field); i < endI; ++i) - PrintEnumValue<false>(TStringBuf(), reflection->GetRepeatedEnum(proto, &field, i), json); - break; - } - - case FieldDescriptor::CPPTYPE_STRING: { - TString scratch; - for (int i = 0, endI = reflection->FieldSize(proto, &field); i < endI; ++i) { - const TString& value = - reflection->GetRepeatedStringReference(proto, &field, i, &scratch); - PrintStringValue<false>(field, TStringBuf(), value, json); - } - break; - } - - default: - ythrow yexception() << "Unknown protobuf field type: " - << static_cast<int>(field.cpp_type()) << "."; + const Reflection* reflection = proto.GetReflection(); + + if (reflection->FieldSize(proto, &field) > 0) { + json.WriteKey(key); + if (isMap) { + json.BeginObject(); + } else { + json.BeginList(); } - if (isMap) { - json.EndObject(); - } else { - json.EndList(); - } - } else { - switch (GetConfig().MissingRepeatedKeyMode) { - case TProto2JsonConfig::MissingKeyNull: { - json.WriteKey(key).WriteNull(); - break; - } - - case TProto2JsonConfig::MissingKeyDefault: { - json.WriteKey(key); - if (isMap) { - json.BeginObject().EndObject(); - } else { - json.BeginList().EndList(); - } - break; - } - - case TProto2JsonConfig::MissingKeySkip: + switch (field.cpp_type()) { + REPEATED_FIELD_TO_JSON(CPPTYPE_INT32, GetRepeatedInt32); + REPEATED_FIELD_TO_JSON(CPPTYPE_INT64, GetRepeatedInt64); + REPEATED_FIELD_TO_JSON(CPPTYPE_UINT32, GetRepeatedUInt32); + REPEATED_FIELD_TO_JSON(CPPTYPE_UINT64, GetRepeatedUInt64); + REPEATED_FIELD_TO_JSON(CPPTYPE_DOUBLE, GetRepeatedDouble); + REPEATED_FIELD_TO_JSON(CPPTYPE_FLOAT, GetRepeatedFloat); + REPEATED_FIELD_TO_JSON(CPPTYPE_BOOL, GetRepeatedBool); + + case FieldDescriptor::CPPTYPE_MESSAGE: { + if (isMap) { + for (size_t i = 0, endI = reflection->FieldSize(proto, &field); i < endI; ++i) { + PrintKeyValue(reflection->GetRepeatedMessage(proto, &field, i), json); + } + } else { + for (size_t i = 0, endI = reflection->FieldSize(proto, &field); i < endI; ++i) { + Print(reflection->GetRepeatedMessage(proto, &field, i), json); + } + } + break; + } + + case FieldDescriptor::CPPTYPE_ENUM: { + for (int i = 0, endI = reflection->FieldSize(proto, &field); i < endI; ++i) + PrintEnumValue<false>(TStringBuf(), reflection->GetRepeatedEnum(proto, &field, i), json); + break; + } + + case FieldDescriptor::CPPTYPE_STRING: { + TString scratch; + for (int i = 0, endI = reflection->FieldSize(proto, &field); i < endI; ++i) { + const TString& value = + reflection->GetRepeatedStringReference(proto, &field, i, &scratch); + PrintStringValue<false>(field, TStringBuf(), value, json); + } + break; + } + + default: + ythrow yexception() << "Unknown protobuf field type: " + << static_cast<int>(field.cpp_type()) << "."; + } + + if (isMap) { + json.EndObject(); + } else { + json.EndList(); + } + } else { + switch (GetConfig().MissingRepeatedKeyMode) { + case TProto2JsonConfig::MissingKeyNull: { + json.WriteKey(key).WriteNull(); + break; + } + + case TProto2JsonConfig::MissingKeyDefault: { + json.WriteKey(key); + if (isMap) { + json.BeginObject().EndObject(); + } else { + json.BeginList().EndList(); + } + break; + } + + case TProto2JsonConfig::MissingKeySkip: case TProto2JsonConfig::MissingKeyExplicitDefaultThrowRequired: - default: - break; + default: + break; } } -#undef REPEATED_FIELD_TO_JSON - } - - void TProto2JsonPrinter::PrintKeyValue(const NProtoBuf::Message& proto, - IJsonOutput& json) { - const FieldDescriptor* keyField = proto.GetDescriptor()->FindFieldByName("key"); - Y_VERIFY(keyField, "Map entry key field not found."); - TString key = MakeKey(proto, *keyField); - const FieldDescriptor* valueField = proto.GetDescriptor()->FindFieldByName("value"); - Y_VERIFY(valueField, "Map entry value field not found."); - PrintField(proto, *valueField, json, key); - } - - TString TProto2JsonPrinter::MakeKey(const NProtoBuf::Message& proto, - const NProtoBuf::FieldDescriptor& field) { - const Reflection* reflection = proto.GetReflection(); - TString result; - switch (field.cpp_type()) { - case FieldDescriptor::CPPTYPE_INT32: - result = ToString(reflection->GetInt32(proto, &field)); - break; - case FieldDescriptor::CPPTYPE_INT64: - result = ToString(reflection->GetInt64(proto, &field)); - break; - case FieldDescriptor::CPPTYPE_UINT32: - result = ToString(reflection->GetUInt32(proto, &field)); - break; - case FieldDescriptor::CPPTYPE_UINT64: - result = ToString(reflection->GetUInt64(proto, &field)); - break; - case FieldDescriptor::CPPTYPE_DOUBLE: - result = ToString(reflection->GetDouble(proto, &field)); - break; - case FieldDescriptor::CPPTYPE_FLOAT: - result = ToString(reflection->GetFloat(proto, &field)); - break; - case FieldDescriptor::CPPTYPE_BOOL: - result = ToString(reflection->GetBool(proto, &field)); - break; - case FieldDescriptor::CPPTYPE_ENUM: { - const EnumValueDescriptor* value = reflection->GetEnum(proto, &field); - switch (GetConfig().EnumMode) { - case TProto2JsonConfig::EnumNumber: - result = ToString(value->number()); - break; - case TProto2JsonConfig::EnumName: - result = value->name(); - break; - case TProto2JsonConfig::EnumFullName: - result = value->full_name(); - break; - case TProto2JsonConfig::EnumNameLowerCase: - result = value->name(); - result.to_lower(); - break; - case TProto2JsonConfig::EnumFullNameLowerCase: - result = value->full_name(); - result.to_lower(); - break; - default: - ythrow yexception() << "Unsupported enum mode."; - } +#undef REPEATED_FIELD_TO_JSON + } + + void TProto2JsonPrinter::PrintKeyValue(const NProtoBuf::Message& proto, + IJsonOutput& json) { + const FieldDescriptor* keyField = proto.GetDescriptor()->FindFieldByName("key"); + Y_VERIFY(keyField, "Map entry key field not found."); + TString key = MakeKey(proto, *keyField); + const FieldDescriptor* valueField = proto.GetDescriptor()->FindFieldByName("value"); + Y_VERIFY(valueField, "Map entry value field not found."); + PrintField(proto, *valueField, json, key); + } + + TString TProto2JsonPrinter::MakeKey(const NProtoBuf::Message& proto, + const NProtoBuf::FieldDescriptor& field) { + const Reflection* reflection = proto.GetReflection(); + TString result; + switch (field.cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + result = ToString(reflection->GetInt32(proto, &field)); + break; + case FieldDescriptor::CPPTYPE_INT64: + result = ToString(reflection->GetInt64(proto, &field)); + break; + case FieldDescriptor::CPPTYPE_UINT32: + result = ToString(reflection->GetUInt32(proto, &field)); + break; + case FieldDescriptor::CPPTYPE_UINT64: + result = ToString(reflection->GetUInt64(proto, &field)); + break; + case FieldDescriptor::CPPTYPE_DOUBLE: + result = ToString(reflection->GetDouble(proto, &field)); + break; + case FieldDescriptor::CPPTYPE_FLOAT: + result = ToString(reflection->GetFloat(proto, &field)); + break; + case FieldDescriptor::CPPTYPE_BOOL: + result = ToString(reflection->GetBool(proto, &field)); + break; + case FieldDescriptor::CPPTYPE_ENUM: { + const EnumValueDescriptor* value = reflection->GetEnum(proto, &field); + switch (GetConfig().EnumMode) { + case TProto2JsonConfig::EnumNumber: + result = ToString(value->number()); + break; + case TProto2JsonConfig::EnumName: + result = value->name(); + break; + case TProto2JsonConfig::EnumFullName: + result = value->full_name(); + break; + case TProto2JsonConfig::EnumNameLowerCase: + result = value->name(); + result.to_lower(); + break; + case TProto2JsonConfig::EnumFullNameLowerCase: + result = value->full_name(); + result.to_lower(); + break; + default: + ythrow yexception() << "Unsupported enum mode."; + } break; - } - case FieldDescriptor::CPPTYPE_STRING: - result = reflection->GetString(proto, &field); - break; - default: - ythrow yexception() << "Unsupported key type."; + } + case FieldDescriptor::CPPTYPE_STRING: + result = reflection->GetString(proto, &field); + break; + default: + ythrow yexception() << "Unsupported key type."; } - return result; + return result; } - void TProto2JsonPrinter::PrintField(const Message& proto, - const FieldDescriptor& field, - IJsonOutput& json, - const TStringBuf key) { + void TProto2JsonPrinter::PrintField(const Message& proto, + const FieldDescriptor& field, + IJsonOutput& json, + const TStringBuf key) { - if (field.is_repeated()) - PrintRepeatedField(proto, field, json, key); - else - PrintSingleField(proto, field, json, key); - } + if (field.is_repeated()) + PrintRepeatedField(proto, field, json, key); + else + PrintSingleField(proto, field, json, key); + } - void TProto2JsonPrinter::Print(const Message& proto, IJsonOutput& json, bool closeMap) { - const Descriptor* descriptor = proto.GetDescriptor(); - Y_ASSERT(descriptor); + void TProto2JsonPrinter::Print(const Message& proto, IJsonOutput& json, bool closeMap) { + const Descriptor* descriptor = proto.GetDescriptor(); + Y_ASSERT(descriptor); - json.BeginObject(); + 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); - Y_ASSERT(field); - PrintField(proto, *field, json); - } + for (int f = 0, endF = descriptor->field_count(); f < endF; ++f) { + const FieldDescriptor* field = descriptor->field(f); + Y_ASSERT(field); + PrintField(proto, *field, json); + } // Check extensions via ListFields std::vector<const FieldDescriptor*> fields; @@ -482,9 +482,9 @@ namespace NProtobufJson { } } - if (closeMap) { - json.EndObject(); - } + if (closeMap) { + json.EndObject(); + } } template <class T, class U> |