aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/protobuf/json/json2proto.h
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/protobuf/json/json2proto.h
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/protobuf/json/json2proto.h')
-rw-r--r--library/cpp/protobuf/json/json2proto.h222
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);
+ }
+
+}