static bool JsonValueToProtoField()

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;
}