diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/protobuf/json/json2proto.h | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/protobuf/json/json2proto.h')
-rw-r--r-- | library/cpp/protobuf/json/json2proto.h | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/library/cpp/protobuf/json/json2proto.h b/library/cpp/protobuf/json/json2proto.h new file mode 100644 index 0000000000..4c33498dfa --- /dev/null +++ b/library/cpp/protobuf/json/json2proto.h @@ -0,0 +1,222 @@ +#pragma once + +#include "string_transform.h" +#include "name_generator.h" + +#include <library/cpp/json/json_reader.h> +#include <library/cpp/json/json_value.h> + +#include <util/stream/input.h> +#include <util/stream/str.h> +#include <util/stream/mem.h> + +namespace google { + namespace protobuf { + class Message; + } +} + +namespace NProtobufJson { + struct TJson2ProtoConfig { + using TSelf = TJson2ProtoConfig; + using TValueVectorizer = std::function<NJson::TJsonValue::TArray(const NJson::TJsonValue& jsonValue)>; + + enum FldNameMode { + FieldNameOriginalCase = 0, // default + FieldNameLowerCase, + FieldNameUpperCase, + FieldNameCamelCase, + FieldNameSnakeCase, // ABC -> a_b_c, UserID -> user_i_d + FieldNameSnakeCaseDense // ABC -> abc, UserID -> user_id + }; + + enum EnumValueMode { + EnumCaseSensetive = 0, // default + EnumCaseInsensetive, + EnumSnakeCaseInsensitive + }; + + TSelf& SetFieldNameMode(FldNameMode mode) { + Y_ENSURE(mode == FieldNameOriginalCase || !UseJsonName, "FieldNameMode and UseJsonName are mutually exclusive"); + FieldNameMode = mode; + return *this; + } + + TSelf& SetUseJsonName(bool jsonName) { + Y_ENSURE(!jsonName || FieldNameMode == FieldNameOriginalCase, "FieldNameMode and UseJsonName are mutually exclusive"); + UseJsonName = jsonName; + return *this; + } + + TSelf& AddStringTransform(TStringTransformPtr transform) { + StringTransforms.push_back(transform); + return *this; + } + + TSelf& SetCastFromString(bool cast) { + CastFromString = cast; + return *this; + } + + TSelf& SetDoNotCastEmptyStrings(bool cast) { + DoNotCastEmptyStrings = cast; + return *this; + } + + TSelf& SetCastRobust(bool cast) { + CastRobust = cast; + return *this; + } + + TSelf& SetMapAsObject(bool mapAsObject) { + MapAsObject = mapAsObject; + return *this; + } + + TSelf& SetReplaceRepeatedFields(bool replaceRepeatedFields) { + ReplaceRepeatedFields = replaceRepeatedFields; + return *this; + } + + TSelf& SetNameGenerator(TNameGenerator callback) { + NameGenerator = callback; + return *this; + } + + TSelf& SetEnumValueMode(EnumValueMode enumValueMode) { + EnumValueMode = enumValueMode; + return *this; + } + + TSelf& SetVectorizeScalars(bool vectorizeScalars) { + VectorizeScalars = vectorizeScalars; + return *this; + } + + TSelf& SetAllowComments(bool value) { + AllowComments = value; + return *this; + } + + TSelf& SetAllowUnknownFields(bool value) { + AllowUnknownFields = value; + return *this; + } + + FldNameMode FieldNameMode = FieldNameOriginalCase; + bool AllowUnknownFields = true; + + /// Use 'json_name' protobuf option for field name, mutually exclusive + /// with FieldNameMode. + bool UseJsonName = false; + + /// Transforms will be applied only to string values (== protobuf fields of string / bytes type). + TVector<TStringTransformPtr> StringTransforms; + + /// Cast string json values to protobuf field type + bool CastFromString = false; + /// Skip empty strings, instead casting from string into scalar types. + /// I.e. empty string like default value for scalar types. + bool DoNotCastEmptyStrings = false; + /// Cast all json values to protobuf field types + bool CastRobust = false; + + /// Consider map to be an object, otherwise consider it to be an array of key/value objects + bool MapAsObject = false; + + /// Throw exception if there is no required fields in json object. + bool CheckRequiredFields = true; + + /// Replace repeated fields content during merging + bool ReplaceRepeatedFields = false; + + /// Custom field names generator. + TNameGenerator NameGenerator = {}; + + /// Enum value parsing mode. + EnumValueMode EnumValueMode = EnumCaseSensetive; + + /// Append scalars to repeated fields + bool VectorizeScalars = false; + + /// Custom spliter non array value to repeated fields. + TValueVectorizer ValueVectorizer; + + /// Allow js-style comments (both // and /**/) + bool AllowComments = false; + }; + + /// @throw yexception + void MergeJson2Proto(const NJson::TJsonValue& json, google::protobuf::Message& proto, + const TJson2ProtoConfig& config = TJson2ProtoConfig()); + + /// @throw yexception + void MergeJson2Proto(const TStringBuf& json, google::protobuf::Message& proto, + const TJson2ProtoConfig& config = TJson2ProtoConfig()); + + /// @throw yexception + inline void MergeJson2Proto(const TString& json, google::protobuf::Message& proto, + const TJson2ProtoConfig& config = TJson2ProtoConfig()) { + MergeJson2Proto(TStringBuf(json), proto, config); + } + + /// @throw yexception + void Json2Proto(const NJson::TJsonValue& json, google::protobuf::Message& proto, + const TJson2ProtoConfig& config = TJson2ProtoConfig()); + + /// @throw yexception + void Json2Proto(const TStringBuf& json, google::protobuf::Message& proto, + const TJson2ProtoConfig& config = TJson2ProtoConfig()); + + /// @throw yexception + inline void Json2Proto(const TString& json, google::protobuf::Message& proto, + const TJson2ProtoConfig& config = TJson2ProtoConfig()) { + Json2Proto(TStringBuf(json), proto, config); + } + + /// @throw yexception + inline void Json2Proto(IInputStream& in, google::protobuf::Message& proto, + const TJson2ProtoConfig& config = TJson2ProtoConfig()) { + Json2Proto(TStringBuf(in.ReadAll()), proto, config); + } + + /// @throw yexception + template <typename T> + T Json2Proto(IInputStream& in, const NJson::TJsonReaderConfig& readerConfig, + const TJson2ProtoConfig& config = TJson2ProtoConfig()) { + NJson::TJsonValue jsonValue; + NJson::ReadJsonTree(&in, &readerConfig, &jsonValue, true); + T protoValue; + Json2Proto(jsonValue, protoValue, config); + return protoValue; + } + + /// @throw yexception + template <typename T> + T Json2Proto(IInputStream& in, const TJson2ProtoConfig& config = TJson2ProtoConfig()) { + NJson::TJsonReaderConfig readerConfig; + readerConfig.DontValidateUtf8 = true; + return Json2Proto<T>(in, readerConfig, config); + } + + /// @throw yexception + template <typename T> + T Json2Proto(const TString& value, const TJson2ProtoConfig& config = TJson2ProtoConfig()) { + TStringInput in(value); + return Json2Proto<T>(in, config); + } + + /// @throw yexception + template <typename T> + T Json2Proto(const TStringBuf& value, const TJson2ProtoConfig& config = TJson2ProtoConfig()) { + TMemoryInput in(value); + return Json2Proto<T>(in, config); + } + + /// @throw yexception + template <typename T> + T Json2Proto(const char* ptr, const TJson2ProtoConfig& config = TJson2ProtoConfig()) { + return Json2Proto<T>(TStringBuf(ptr), config); + } + +} |