How To Serialize Knowledge Successfully with Protocol Buffers – Grape Up

In a world of microservices, we frequently need to cross data between functions. We serialize information right into a format that may be retrieved by each side. One of many serialization options is Protocol Buffers (Protobuf) – Google’s language-neutral mechanism. Messages might be interpreted by a receiver utilizing the identical or totally different language than a producer. Many languages are supported, akin to Java, Go, Python, and C++.

An information construction is outlined utilizing impartial language by .proto information. The file is then compiled into code for use in functions. It’s designed for efficiency. Protocol Buffers encode information into binary format, which reduces message dimension and improves transmission pace.

Defining Message Format

This .proto the file represents geolocation data for a given car.

1syntax = "proto3";
3package com.grapeup.geolocation;
5import "google/kind/latlng.proto";
6import "google/protobuf/timestamp.proto";
8message Geolocation {
9  string vin = 1;
10  google.protobuf.Timestamp occurredOn = 2;
11  int32 pace = 3;
12  google.kind.LatLng coordinates = 4;
1syntax = "proto3";

Syntax refers to Protobuf model, it may be proto2 or proto3.

1package com.grapeup.geolocation;

Bundle declaration prevents naming conflicts between totally different tasks.

1message Geolocation {
2  string vin = 1;
3  google.protobuf.Timestamp occurredOn = 2;
4  int32 pace = 3;
5  google.kind.LatLng coordinates = 4;

Message definition comprises a reputation and a set of typed fields. Easy information varieties can be found, akin to bool, int32, double, string, and so forth. You may as well outline your personal varieties or import them.

1google.protobuf.Timestamp occurredOn = 2;

The = 1, = 2 markers establish the distinctive tag. Tags are a numeric illustration for the sector and are used to establish the sector within the message binary format. They need to be distinctive in a message and shouldn’t be modified as soon as the message is in use. If a area is faraway from a definition that’s already used, it should be reserved.

Subject varieties

Apart from scalar varieties, there are numerous different kind choices when defining messages. Listed here are few, however you could find all of them within the Language Information Language Information (proto3)  |  Protocol Buffers  |  Google Builders .

Nicely Identified Varieties

1import "google/kind/latlng.proto";
2import "google/protobuf/timestamp.proto";
4google.protobuf.Timestamp occurredOn = 2;
5google.kind.LatLng coordinates = 4;

There are predefined varieties out there to make use of Overview  |  Protocol Buffers  |  Google Builders . They’re referred to as Nicely Know Varieties and need to be imported into .proto .

LatLng represents a latitude and longitude pair.

Timestamp is a particular time limit with nanosecond precision.

Customized varieties

1message SingularSearchResponse {
2  Geolocation geolocation = 1;

You should utilize your custom-defined kind as a area in one other message definition.


1message SearchResponse {
2  repeated Geolocation geolocations = 1;

You’ll be able to outline lists through the use of repeated key phrase.


It could occur that in a message there’ll all the time be just one area set. On this case, TelemetryUpdate will comprise both geolocation, mileage, or gas degree data.

This may be achieved through the use of oneof. Setting worth to one of many fields will clear all different fields outlined in oneof.

1message TelemetryUpdate {
2  string vin = 1;
3  oneof replace {
4    Geolocation geolocation = 2;
5    Mileage mileage =3;
6    FuelLevel fuelLevel = 4;
7  }
10message Geolocation {
11  ...
14message Mileage {
15  ...
18message FuelLevel {
19  ...

Be mindful backward-compatibility when eradicating fields. When you obtain a message with oneof that has been faraway from .proto definition, it is not going to set any of the values. This habits is identical as not setting any worth within the first place.

You’ll be able to carry out totally different actions based mostly on which worth is ready utilizing the getUpdateCase() methodology.

1 public Elective<Object> getTelemetry(TelemetryUpdate telemetryUpdate) {
2        Elective<Object> telemetry = Elective.empty();
3        change (telemetryUpdate.getUpdateCase()) {
4            case MILEAGE -> telemetry = Elective.of(telemetryUpdate.getMileage());
5            case FUELLEVEL -> telemetry = Elective.of(telemetryUpdate.getFuelLevel());
6            case GEOLOCATION -> telemetry = Elective.of(telemetryUpdate.getGeolocation());
7            case UPDATE_NOT_SET -> telemetry = Elective.empty();
8        }
9        return telemetry;
10    }

Default values

In proto3 format fields will all the time have a price. Due to this proto3 can have a smaller dimension as a result of fields with default values are omitted from payload. Nevertheless this causes one subject – for scalar message fields, there isn’t any method of telling if a area was explicitly set to the default worth or not set in any respect.

In our instance, pace is an optionally available area – some modules in a automobile may ship pace information, and a few won’t. If we don’t set pace, then the geolocation object may have pace with the default worth set to 0. This isn’t the identical as not having pace set on messages.

As a way to cope with default values you should use official wrapper varieties protobuf/wrappers.proto at foremost · protocolbuffers/protobuf . They permit distinguishing between absence and default. As an alternative of getting a easy kind, we use Int32Value, which is a wrapper for the int32 scalar kind.

1import "google/protobuf/wrappers.proto";
3message Geolocation {
4  google.protobuf.Int32Value pace = 3;

If we don’t present pace, it will likely be set to nil.

Configure with Gradle

When you’ve outlined your messages, you should use protoc, a protocol buffer compiler, to generate lessons in a selected language. The generated class can then be used to construct and retrieve messages.

As a way to compile into Java code, we have to add dependency and plugin in construct.gradle

1plugins {
2    id '' model '0.8.18'
5dependencies {
6    implementation ''

and setup the compiler. For Mac customers an osx particular model needs to be used.

1protobuf {
2    protoc {
3        if (osdetector.os == "osx") {
4            artifact = "${protobuf_version}:osx-x86_64"
5        } else {
6            artifact = "${protobuf_version}"
7        }
8    }

Code will likely be generated utilizing generateProto job.

The code will likely be positioned in construct/generated/supply/proto/foremost/java in a bundle as laid out in .proto file.

We additionally want to inform gradle the place the generated code is positioned

1sourceSets {
2    foremost {
3        java {
4            srcDirs 'construct/generated/supply/proto/foremost/grpc'
5            srcDirs 'construct/generated/supply/proto/foremost/java'
6        }
7    }

The generated class comprises all the mandatory strategies for constructing the message in addition to retrieving area values.

1Geolocation geolocation = Geolocation.newBuilder()
2            .setCoordinates(LatLng.newBuilder().setLatitude(1.2).setLongitude(1.2).construct())
3            .setVin("1G2NF12FX2C129610")
4            .setOccurredOn(Timestamp.newBuilder().setSeconds(12349023).construct())
5            .construct();
7LatLng coordinates = geolocation.getCoordinates();
8String vin = geolocation.getVin();

Protocol Buffers – Abstract

As proven protocol buffers are simply configured. The mechanism is language agnostic, and it’s straightforward to share the identical .proto definition throughout totally different microservices.

Protobuf is definitely paired with gRPC, the place strategies might be outlined in .proto information and generated with gradle.

There may be official documentation out there Protocol Buffers  |  Google Builders and guides Language Information (proto3)  |  Protocol Buffers  |  Google Builders .


Leave a Reply

    Your Cart
    Your cart is emptyReturn to Shop