Extended Types (google.type.*
) in Protocol Buffers
Extended types (google.type.*
) are domain-specific Protobuf types that standardize complex data structures. They are part of the googleapis
repository and provide reusable definitions for common use cases like money, geolocation, and dates. This documentation covers all major extended types with examples, usage guidelines, and best practices.
1. google.type.Money
Represents a monetary amount with currency precision.
Syntax
import "google/type/money.proto";
message BalanceResponse {
google.type.Money balance = 1;
}
Key Features
- Currency Code: ISO 4217 (e.g.,
"USD"
,"EUR"
). - Units/Nanos:
units
(integer part) andnanos
(fractional part, 0–999,999,999).
Example: Bank Account Balance
Proto File (extended_money.proto
):
syntax = "proto3";
import "google/type/money.proto";
package extended;
service MoneyService {
rpc GetBalance(BalanceRequest) returns (BalanceResponse) {}
}
message BalanceRequest {
string accountId = 1;
}
message BalanceResponse {
google.type.Money balance = 1;
}
Stub Configuration (extended_money.yaml
):
- service: MoneyService
method: GetBalance
input:
equals:
accountId: "user_123"
output:
data:
balance:
currencyCode: "USD"
units: 100
nanos: 500000000 # $100.50
Test Command:
grpcurl -plaintext -d '{"accountId": "user_123"}' localhost:4770 extended.MoneyService/GetBalance
Output:
{
"balance": {
"currencyCode": "USD",
"units": "100",
"nanos": 500000000
}
}
2. google.type.LatLng
Represents geographic coordinates (latitude and longitude).
Syntax
import "google/type/latlng.proto";
message LocationResponse {
google.type.LatLng coordinates = 1;
}
Key Features
- Precision: Floating-point values with up to 8 decimal places.
- Validation: Latitude must be in
[-90, 90]
, longitude in[-180, 180]
.
Example: Geolocation Service
Proto File (extended_latlng.proto
):
syntax = "proto3";
import "google/type/latlng.proto";
package extended;
service LocationService {
rpc GetCoordinates(LocationRequest) returns (LocationResponse) {}
}
message LocationRequest {
string address = 1;
}
message LocationResponse {
google.type.LatLng coordinates = 1;
}
Stub Configuration (extended_latlng.yaml
):
- service: LocationService
method: GetCoordinates
input:
equals:
address: "Eiffel Tower"
output:
data:
coordinates:
latitude: 48.8584
longitude: 2.2945
Test Command:
grpcurl -plaintext -d '{"address": "Eiffel Tower"}' localhost:4770 extended.LocationService/GetCoordinates
Output:
{
"coordinates": {
"latitude": 48.8584,
"longitude": 2.2945
}
}
3. google.type.DateTime
and google.type.TimeZone
Represents a date, time, and time zone.
Syntax
import "google/type/datetime.proto";
message EventResponse {
google.type.DateTime eventTime = 1;
google.type.TimeZone timeZone = 2;
}
Key Features
- Date/Time Fields: Year, month, day, hours, minutes, seconds.
- Time Zone: IANA name (e.g.,
"America/New_York"
) or UTC offset.
Example: Event Scheduler
Proto File (extended_datetime.proto
):
syntax = "proto3";
import "google/type/datetime.proto";
package extended;
service DateTimeService {
rpc GetEventTime(DateTimeRequest) returns (DateTimeResponse) {}
}
message DateTimeRequest {
string eventId = 1;
}
message DateTimeResponse {
google.type.DateTime eventTime = 1;
google.type.TimeZone timeZone = 2;
}
Stub Configuration (extended_datetime.yaml
):
- service: DateTimeService
method: GetEventTime
input:
equals:
eventId: "event_123"
output:
data:
eventTime:
year: 2024
month: 12
day: 25
hours: 18
minutes: 30
seconds: 1
timeZone:
id: "Europe/London"
Test Command:
grpcurl -plaintext -d '{"eventId": "event_123"}' localhost:4770 extended.DateTimeService/GetEventTime
Output:
{
"eventTime": {
"day": 25,
"hours": 18,
"minutes": 30,
"month": 12,
"seconds": 1,
"year": 2024
},
"timeZone": {
"id": "Europe/London"
}
}
4. google.type.Date
and google.type.TimeOfDay
Represents a date without time and a time without a date.
Syntax
import "google/type/date.proto";
import "google/type/timeofday.proto";
message Schedule {
google.type.Date date = 1;
google.type.TimeOfDay time = 2;
}
Example: Birthday Reminder
Proto File (extended_date.proto
):
syntax = "proto3";
import "google/type/date.proto";
import "google/type/timeofday.proto";
package extended;
service ScheduleService {
rpc GetBirthday(BirthdayRequest) returns (BirthdayResponse) {}
}
message BirthdayRequest {
string userId = 1;
}
message BirthdayResponse {
google.type.Date date = 1;
google.type.TimeOfDay reminderTime = 2;
}
Stub Configuration (extended_date.yaml
):
- service: ScheduleService
method: GetBirthday
input:
equals:
userId: "user_123"
output:
data:
date:
year: 1990
month: 5
day: 15
reminderTime:
hours: 9
minutes: 1
seconds: 2
nanos: 3000000
Test Command:
grpcurl -plaintext -d '{"userId": "user_123"}' localhost:4770 extended.ScheduleService/GetBirthday
Output:
{
"date": {
"year": 1990,
"month": 5,
"day": 15
},
"reminderTime": {
"hours": 9,
"minutes": 1,
"seconds": 2,
"nanos": 3000000
}
}
5. google.type.PostalAddress
Represents a structured postal address.
Syntax
import "google/type/postal_address.proto";
message AddressResponse {
google.type.PostalAddress address = 1;
}
Key Features
- Structured Fields: Recipient, street, city, region, postal code, etc.
- Localization: Supports international addresses.
Example: Address Validation
Proto File (extended_postaladdress.proto
):
syntax = "proto3";
import "google/type/postal_address.proto";
package extended;
service AddressService {
rpc ValidateAddress(AddressRequest) returns (AddressResponse) {}
}
message AddressRequest {
string addressId = 1;
}
message AddressResponse {
google.type.PostalAddress validatedAddress = 1;
}
Stub Configuration (extended_postaladdress.yaml
):
- service: AddressService
method: ValidateAddress
input:
equals:
addressId: "addr_123"
output:
data:
validatedAddress:
regionCode: "US"
postalCode: "94043"
administrativeArea: "CA"
locality: "Mountain View"
addressLines: ["1600 Amphitheatre Parkway"]
recipients: ["Google Inc."]
Test Command:
grpcurl -plaintext -d '{"addressId": "addr_123"}' localhost:4770 extended.AddressService/ValidateAddress
Output:
{
"validatedAddress": {
"regionCode": "US",
"postalCode": "94043",
"administrativeArea": "CA",
"locality": "Mountain View",
"addressLines": ["1600 Amphitheatre Parkway"],
"recipients": ["Google Inc."]
}
}
6. google.type.Color
Represents a color in RGB/RGBA format.
Syntax
import "google/type/color.proto";
message DesignResponse {
google.type.Color primaryColor = 1;
}
Example: Design Tool
Proto File (extended_color.proto
):
syntax = "proto3";
import "google/type/color.proto";
package extended;
service DesignService {
rpc GetThemeColor(ColorRequest) returns (ColorResponse) {}
}
message ColorRequest {
string themeId = 1;
}
message ColorResponse {
google.type.Color color = 1;
}
Stub Configuration (extended_color.yaml
):
- service: DesignService
method: GetThemeColor
input:
equals:
themeId: "dark_theme"
output:
data:
color:
red: 0.1
green: 0.2
blue: 0.3
alpha: 0.8
Test Command:
grpcurl -plaintext -d '{"themeId": "dark_theme"}' localhost:4770 extended.DesignService/GetThemeColor
Output:
{
"color": {
"red": 0.1,
"green": 0.2,
"blue": 0.3,
"alpha": 0.8
}
}
7. google.type.Interval
Represents a time interval with start and end times.
Syntax
import "google/type/interval.proto";
message BookingResponse {
google.type.Interval booking_time = 1;
}
Example: Booking System
Proto File (extended_interval.proto
):
syntax = "proto3";
import "google/type/interval.proto";
package extended;
service BookingService {
rpc GetBooking(BookingRequest) returns (BookingResponse) {}
}
message BookingRequest {
string bookingId = 1;
}
message BookingResponse {
google.type.Interval bookingTime = 1;
}
Stub Configuration (extended_interval.yaml
):
- service: BookingService
method: GetBooking
input:
equals:
bookingId: "booking_123"
output:
data:
bookingTime:
startTime: "2024-01-01T00:00:00Z"
endTime: "2024-01-01T23:59:59Z"
Test Command:
grpcurl -plaintext -d '{"bookingId": "booking_123"}' localhost:4770 extended.BookingService/GetBooking
Output:
{
"bookingTime": {
"endTime": "2024-01-01T23:59:59Z",
"startTime": "2024-01-01T00:00:00Z"
}
}
8. google.protobuf.Empty
Represents an empty request or response (placeholder for no data).
Syntax
import "google/protobuf/empty.proto";
service ExampleService {
rpc GetData(google.protobuf.Empty) returns (DataResponse) {}
}
Key Features
- Used for RPC methods that require no input or return no data.
- Commonly used for operations like health checks, status resets, or triggering background processes.
Example: Service with Empty Input
Proto File (extended_empty.proto
):
syntax = "proto3";
import "google/protobuf/empty.proto";
package extended;
service EmptyService {
rpc GetData(google.protobuf.Empty) returns (DataResponse) {}
}
message DataResponse {
string content = 1;
}
Stub Configuration (extended_empty.yaml
):
- service: EmptyService
method: GetData
input:
matches: {} # Required for empty input in Gripmock
output:
data:
content: "test"
code: 0
Test Command:
grpcurl -plaintext -d '{}' localhost:4770 extended.EmptyService/GetData
Output:
{
"content": "test"
}
Gripmock Specific Behavior
For RPC methods with empty input (e.g., rpc GetData(google.protobuf.Empty)
), always specify input.matches: {}
in the stub configuration. This ensures Gripmock correctly handles the absence of input data.
Best Practices
- Currency Codes: Always use ISO 4217 codes (e.g.,
"USD"
) withMoney
. - Time Zones: Prefer IANA names (e.g.,
"America/New_York"
) over UTC offsets. - Validation: Ensure
LatLng
values are within valid ranges. - Postal Addresses: Use
address_lines
for street-level details andadministrative_area
for regions/states.
Common Pitfalls
- Money Precision: Avoid using
float
/double
for money; useunits
andnanos
. - DateTime Defaults: Missing
time_zone
may lead to ambiguous times. - Color Alpha:
alpha
is optional (defaults to 1.0), but always specify it for transparency.