|
@@ -24,6 +24,7 @@
|
|
|
#include <typeinfo>
|
|
|
#include <limits>
|
|
|
#include <google/protobuf/descriptor.h>
|
|
|
+#include "butil/strings/string_number_conversions.h"
|
|
|
#include "json_to_pb.h"
|
|
|
#include "zero_copy_stream_reader.h" // ZeroCopyStreamReader
|
|
|
#include "encode_decode.h"
|
|
@@ -207,10 +208,63 @@ inline bool convert_enum_type(const BUTIL_RAPIDJSON_NAMESPACE::Value&item, bool
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+inline bool convert_int64_type(const BUTIL_RAPIDJSON_NAMESPACE::Value& item, bool repeated,
|
|
|
+ google::protobuf::Message* message,
|
|
|
+ const google::protobuf::FieldDescriptor* field,
|
|
|
+ const google::protobuf::Reflection* reflection,
|
|
|
+ std::string* err) {
|
|
|
+
|
|
|
+ int64_t num;
|
|
|
+ if (item.IsInt64()) {
|
|
|
+ if (repeated) {
|
|
|
+ reflection->AddInt64(message, field, item.GetInt64());
|
|
|
+ } else {
|
|
|
+ reflection->SetInt64(message, field, item.GetInt64());
|
|
|
+ }
|
|
|
+ } else if (item.IsString() &&
|
|
|
+ butil::StringToInt64({item.GetString(), item.GetStringLength()},
|
|
|
+ &num)) {
|
|
|
+ if (repeated) {
|
|
|
+ reflection->AddInt64(message, field, num);
|
|
|
+ } else {
|
|
|
+ reflection->SetInt64(message, field, num);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return value_invalid(field, "INT64", item, err);
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+inline bool convert_uint64_type(const BUTIL_RAPIDJSON_NAMESPACE::Value& item,
|
|
|
+ bool repeated,
|
|
|
+ google::protobuf::Message* message,
|
|
|
+ const google::protobuf::FieldDescriptor* field,
|
|
|
+ const google::protobuf::Reflection* reflection,
|
|
|
+ std::string* err) {
|
|
|
+ uint64_t num;
|
|
|
+ if (item.IsUint64()) {
|
|
|
+ if (repeated) {
|
|
|
+ reflection->AddUInt64(message, field, item.GetUint64());
|
|
|
+ } else {
|
|
|
+ reflection->SetUInt64(message, field, item.GetUint64());
|
|
|
+ }
|
|
|
+ } else if (item.IsString() &&
|
|
|
+ butil::StringToUint64({item.GetString(), item.GetStringLength()},
|
|
|
+ &num)) {
|
|
|
+ if (repeated) {
|
|
|
+ reflection->AddUInt64(message, field, num);
|
|
|
+ } else {
|
|
|
+ reflection->SetUInt64(message, field, num);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return value_invalid(field, "UINT64", item, err);
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
bool JsonValueToProtoMessage(const BUTIL_RAPIDJSON_NAMESPACE::Value& json_value,
|
|
|
google::protobuf::Message* message,
|
|
|
- const Json2PbOptions& options,
|
|
|
- std::string* err);
|
|
|
+ const Json2PbOptions& options, std::string* err);
|
|
|
|
|
|
//Json value to protobuf convert rules for type:
|
|
|
//Json value type Protobuf type convert rules
|
|
@@ -219,9 +273,10 @@ bool JsonValueToProtoMessage(const BUTIL_RAPIDJSON_NAMESPACE::Value& json_value,
|
|
|
//int64 int uint int64 uint64 valid convert is available
|
|
|
//uint64 int uint int64 uint64 valid convert is available
|
|
|
//int uint int64 uint64 float double available
|
|
|
-//"NaN" "Infinity" "-Infinity" float double only "NaN" "Infinity" "-Infinity" is available
|
|
|
+//"NaN" "Infinity" "-Infinity" float double only "NaN" "Infinity" "-Infinity" is available
|
|
|
//int enum valid enum number value is available
|
|
|
-//string enum valid enum name value is available
|
|
|
+//string enum valid enum name value is available
|
|
|
+//string int64 uint64 valid convert is available
|
|
|
//other mismatch type convertion will be regarded as error.
|
|
|
#define J2PCHECKTYPE(value, cpptype, jsontype) ({ \
|
|
|
MatchType match_type = TYPE_MATCH; \
|
|
@@ -234,6 +289,7 @@ bool JsonValueToProtoMessage(const BUTIL_RAPIDJSON_NAMESPACE::Value& json_value,
|
|
|
match_type; \
|
|
|
})
|
|
|
|
|
|
+
|
|
|
static bool JsonValueToProtoField(const BUTIL_RAPIDJSON_NAMESPACE::Value& value,
|
|
|
const google::protobuf::FieldDescriptor* field,
|
|
|
google::protobuf::Message* message,
|
|
@@ -271,15 +327,48 @@ static bool JsonValueToProtoField(const BUTIL_RAPIDJSON_NAMESPACE::Value& value,
|
|
|
reflection->Set##method(message, field, value.Get##jsontype()); \
|
|
|
} \
|
|
|
break; \
|
|
|
- }
|
|
|
+ } \
|
|
|
+
|
|
|
CASE_FIELD_TYPE(INT32, Int32, Int);
|
|
|
CASE_FIELD_TYPE(UINT32, UInt32, Uint);
|
|
|
CASE_FIELD_TYPE(BOOL, Bool, Bool);
|
|
|
- CASE_FIELD_TYPE(INT64, Int64, Int64);
|
|
|
- CASE_FIELD_TYPE(UINT64, UInt64, Uint64);
|
|
|
#undef CASE_FIELD_TYPE
|
|
|
|
|
|
- case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
|
|
|
+ case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
|
|
|
+ if (field->is_repeated()) {
|
|
|
+ const BUTIL_RAPIDJSON_NAMESPACE::SizeType size = value.Size();
|
|
|
+ for (BUTIL_RAPIDJSON_NAMESPACE::SizeType index = 0; index < size;
|
|
|
+ ++index) {
|
|
|
+ const BUTIL_RAPIDJSON_NAMESPACE::Value& item = value[index];
|
|
|
+ if (!convert_int64_type(item, true, message, field, reflection,
|
|
|
+ err)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (!convert_int64_type(value, false, message, field, reflection,
|
|
|
+ err)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
|
|
|
+ if (field->is_repeated()) {
|
|
|
+ const BUTIL_RAPIDJSON_NAMESPACE::SizeType size = value.Size();
|
|
|
+ for (BUTIL_RAPIDJSON_NAMESPACE::SizeType index = 0; index < size;
|
|
|
+ ++index) {
|
|
|
+ const BUTIL_RAPIDJSON_NAMESPACE::Value& item = value[index];
|
|
|
+ if (!convert_uint64_type(item, true, message, field, reflection,
|
|
|
+ err)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (!convert_uint64_type(value, false, message, field, reflection,
|
|
|
+ err)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
|
|
|
if (field->is_repeated()) {
|
|
|
const BUTIL_RAPIDJSON_NAMESPACE::SizeType size = value.Size();
|
|
|
for (BUTIL_RAPIDJSON_NAMESPACE::SizeType index = 0; index < size; ++index) {
|