Image by David Mark from Pixabay

Imagine you have the follow Protocol Buffer / gRPC definition:

service MyDataService {

rpc UpateMyData (UpdateMyDataRequest)

returns (UpdateMyDataResponse);

} message MyData {

int32 id = 1;

string stringValue = 2;

SubData subData = 3;

}



message SubData {

int64 bigValue = 1;

} message UpdateMyDataRequest {

MyData update = 1;

}

Now let's say you want to remove the database entry for MyData.stringValue

Your first approach would probably be something like this:

UpdateMyDataRequest request = UpdateMyDataRequest.newBuilder()

.setUpdate(MyData.newBuilder()

.setId(id)

.setStringValue(null)

)



serviceFutureStub.update(request)

Only as soon as you go to run you will get a NullPointerException.

By default, setting any value in the protoc generated MessageTypes throws a NullPointerException. And on the flip side all get methods never return null. If they are unset the get will return a default value.

UpdateMyDataRequest.newBuilder().build().getStringValue() == ""

How do send a null value with Protocol Buffers?

Let me answer your question, with a question of my own.

What does it mean to be null?

The problem is null can mean different things in different contexts:

Null is null

Null is unset/optional

Null is default

Null is confused with other values

To avoid this confusion the Protobuf team decided to not serialize null values. Instead, protobuf forces you to use several explicit strategies, thereby avoiding any semantic confusion in your Protobuf / gRPC API.

In the following sections, we will address each of the null use cases outlined above and how we can represent them with Protobuf.

We are going to focus on proto3. Proto2 has other semantics that we won’t go into here.

First some basic knowledge proto3

All Fields are: