Skip to content

Extended Types (google.type.*) in Protocol Buffers v2.7.1 ​

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.

1. google.type.Money ​

Represents a monetary amount with currency precision.

Syntax ​

proto
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) and nanos (fractional part, 0–999,999,999).

Example: Bank Account Balance ​

Proto File (extended_money.proto):

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):

yaml
- service: MoneyService
  method: GetBalance
  input:
    equals:
      accountId: "user_123"
  output:
    data:
      balance:
        currencyCode: "USD"
        units: 100
        nanos: 500000000  # $100.50

Test Command:

sh
grpcurl -plaintext -d '{"accountId": "user_123"}' localhost:4770 extended.MoneyService/GetBalance

Output:

json
{
  "balance": {
    "currencyCode": "USD",
    "units": "100",
    "nanos": 500000000
  }
}

2. google.type.LatLng ​

Represents geographic coordinates (latitude and longitude).

Syntax ​

proto
import "google/type/latlng.proto";

message LocationResponse {
  google.type.LatLng coordinates = 1;
}

Key Features ​

  • Precision: both fields are double.
  • Ranges: latitude belongs in [-90, 90], longitude in [-180, 180]. The type does not enforce this.

Example: Geolocation Service ​

Proto File (extended_latlng.proto):

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):

yaml
- service: LocationService
  method: GetCoordinates
  input:
    equals:
      address: "Eiffel Tower"
  output:
    data:
      coordinates:
        latitude: 48.8584
        longitude: 2.2945

Test Command:

sh
grpcurl -plaintext -d '{"address": "Eiffel Tower"}' localhost:4770 extended.LocationService/GetCoordinates

Output:

json
{
  "coordinates": {
    "latitude": 48.8584,
    "longitude": 2.2945
  }
}

3. google.type.DateTime and google.type.TimeZone ​

Represents a date, time, and time zone.

Syntax ​

proto
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):

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):

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:

sh
grpcurl -plaintext -d '{"eventId": "event_123"}' localhost:4770 extended.DateTimeService/GetEventTime

Output:

json
{
  "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 ​

proto
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):

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):

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:

sh
grpcurl -plaintext -d '{"userId": "user_123"}' localhost:4770 extended.ScheduleService/GetBirthday

Output:

json
{
  "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 ​

proto
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):

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):

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:

sh
grpcurl -plaintext -d '{"addressId": "addr_123"}' localhost:4770 extended.AddressService/ValidateAddress

Output:

json
{
  "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 ​

proto
import "google/type/color.proto";

message DesignResponse {
  google.type.Color primaryColor = 1;
}

Example: Design Tool ​

Proto File (extended_color.proto):

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):

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:

sh
grpcurl -plaintext -d '{"themeId": "dark_theme"}' localhost:4770 extended.DesignService/GetThemeColor

Output:

json
{
  "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 ​

proto
import "google/type/interval.proto";

message BookingResponse {
  google.type.Interval booking_time = 1;
}

Example: Booking System ​

Proto File (extended_interval.proto):

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):

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:

sh
grpcurl -plaintext -d '{"bookingId": "booking_123"}' localhost:4770 extended.BookingService/GetBooking

Output:

json
{
  "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 ​

proto
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):

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):

yaml
- service: EmptyService  
  method: GetData  
  input:  
    equals: {}  # empty matcher — matches any request  
  output:  
    data:  
      content: "test"  
    code: 0

Test Command:

sh
grpcurl -plaintext -d '{}' localhost:4770 extended.EmptyService/GetData

Output:

json
{  
  "content": "test"  
}

GripMock Specific Behavior ​

For an RPC with empty input (rpc GetData(google.protobuf.Empty)) give the stub an empty matcher — equals: {} — so it matches the empty request. Any strategy works here, since an empty matcher map always passes; equals: {} is the form used elsewhere in these docs.

Best Practices ​

  1. Currency Codes: Always use ISO 4217 codes (e.g., "USD") with Money.
  2. Time Zones: Prefer IANA names (e.g., "America/New_York") over UTC offsets.
  3. Validation: Ensure LatLng values are within valid ranges.
  4. Postal Addresses: Use addressLines for street-level details and administrativeArea for regions/states.

Common Pitfalls ​

  • Money Precision: Avoid using float/double for money; use units and nanos.
  • 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.

Further Reading ​