in src/json2pb/json_to_pb.cpp [313:492]
static bool JsonValueToProtoField(const BUTIL_RAPIDJSON_NAMESPACE::Value& value,
const google::protobuf::FieldDescriptor* field,
google::protobuf::Message* message,
const Json2PbOptions& options,
std::string* err) {
if (value.IsNull()) {
if (field->is_required()) {
J2PERROR(err, "Missing required field: %s", field->full_name().c_str());
return false;
}
return true;
}
if (field->is_repeated()) {
if (!value.IsArray()) {
J2PERROR(err, "Invalid value for repeated field: %s",
field->full_name().c_str());
return false;
}
}
const google::protobuf::Reflection* reflection = message->GetReflection();
switch (field->cpp_type()) {
#define CASE_FIELD_TYPE(cpptype, method, jsontype) \
case google::protobuf::FieldDescriptor::CPPTYPE_##cpptype: { \
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 (TYPE_MATCH == J2PCHECKTYPE(item, cpptype, jsontype)) { \
reflection->Add##method(message, field, item.Get##jsontype()); \
} \
} \
} else if (TYPE_MATCH == J2PCHECKTYPE(value, cpptype, jsontype)) { \
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);
#undef CASE_FIELD_TYPE
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) {
const BUTIL_RAPIDJSON_NAMESPACE::Value & item = value[index];
if (!convert_float_type(item, true, message, field,
reflection, err)) {
return false;
}
}
} else if (!convert_float_type(value, false, message, field,
reflection, err)) {
return false;
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
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_double_type(item, true, message, field,
reflection, err)) {
return false;
}
}
} else if (!convert_double_type(value, false, message, field,
reflection, err)) {
return false;
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
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 (TYPE_MATCH == J2PCHECKTYPE(item, string, String)) {
std::string str(item.GetString(), item.GetStringLength());
if (field->type() == google::protobuf::FieldDescriptor::TYPE_BYTES &&
options.base64_to_bytes) {
std::string str_decoded;
if (!butil::Base64Decode(str, &str_decoded)) {
J2PERROR_WITH_PB(message, err, "Fail to decode base64 string=%s", str.c_str());
return false;
}
str = str_decoded;
}
reflection->AddString(message, field, str);
}
}
} else if (TYPE_MATCH == J2PCHECKTYPE(value, string, String)) {
std::string str(value.GetString(), value.GetStringLength());
if (field->type() == google::protobuf::FieldDescriptor::TYPE_BYTES &&
options.base64_to_bytes) {
std::string str_decoded;
if (!butil::Base64Decode(str, &str_decoded)) {
J2PERROR_WITH_PB(message, err, "Fail to decode base64 string=%s", str.c_str());
return false;
}
str = str_decoded;
}
reflection->SetString(message, field, str);
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
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_enum_type(item, true, message, field,
reflection, err)) {
return false;
}
}
} else if (!convert_enum_type(value, false, message, field,
reflection, err)) {
return false;
}
break;
case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
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 (TYPE_MATCH == J2PCHECKTYPE(item, message, Object)) {
if (!JsonValueToProtoMessage(
item, reflection->AddMessage(message, field), options, err)) {
return false;
}
}
}
} else if (!JsonValueToProtoMessage(
value, reflection->MutableMessage(message, field), options, err)) {
return false;
}
break;
}
return true;
}