Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compile protobuf to use primitive classes instead of well-known types

Lets say I have test.proto file:

syntax = "proto3";

option java_package = "testing";
option java_outer_classname = "Test_v1";

import "google/protobuf/wrappers.proto";

message TestMessage {
    .google.protobuf.Int32Value integerField = 1;
}

If I compile (using protoc v3.5.0) it to c# code I will get nullable type properties:

public int? IntegerField {
   get { return integerField_; }
   set { integerField_ = value; }
 }

But if I compile it to Java code, fields will be of well-known type:

public Builder setIntegerField(com.google.protobuf.Int32Value value) {
  if (integerFieldBuilder_ == null) {
    if (value == null) {
      throw new NullPointerException();
    }
    integerField_ = value;
    onChanged();
  } else {
    integerFieldBuilder_.setMessage(value);
 }

I am moving project from proto2 to proto3 so I would like to avoid using well-known types, because it will require a lot of work to change related code. With c# projects I will not require to modify anything but in Java I will need to do as in the following example:

TestMessage.Builder builder = TestMessage.newBuilder();
builder.setIntegerField(5); //<-- instead of this with proto2
builder.setIntegerField(Int32Value.newBuilder().setValue(5)); //<-- I will need to do something like this with proto3

Is there a way to compile proto file to Java so setters would accept primitive classes/wrappers (String, Integer, etc.) as parameters?

like image 317
Renatas M. Avatar asked Oct 17 '22 00:10

Renatas M.


1 Answers

The issue here is what to do when the value is missing. This isn't an issue with int32 (in the .proto), as (in proto3, at least) an int32 will always be there (defaulting to 0). However, an .google.protobuf.Int32Value is a message, and as such it can be missing, or represent a value (which might be 0). In C# this concept can be neatly represented via int? (which can be null), but Java has no concept similar to Nullable<T>. The Int32Value encapsulates this, allowing a null reference.

So short version: no, and (^^^) that's why.

I assume you're actually replacing something that used to be:

message TestMessage {
    optional int32 integerField = 1;
}

???

like image 53
Marc Gravell Avatar answered Oct 20 '22 23:10

Marc Gravell