Singular fields in Proto 3 are incorrectly treated as required
Nobody has claimed this yet.
- Dominant language
- Kotlin
- Stars
- 4.4k
- Forks
- 627
- Avg merge
- 3d 15m
- Merged PRs (30d)
- 20
Description
Wire seems to treat singular fields in Proto 3 schemas as if they are required, generating non-nullable setters / getters / etc.
This seems to conflict with the behaviour described in the protobuf language guide, which describes singular as being closer to optional than to required.
Specifically, I would expect that a singular field in a proto3 definition would generate a "setter" function that accepts null as input (clearing the value), and a non-nullable "getter" function that substitutes the appropriate default if no value is present in the serialised message.
Example:
syntax = "proto2";
message Proto2Format {
optional string field_1 = 1;
optional string field_2 = 2;
}
syntax = "proto3";
message Proto3Format {
string field_1 = 1;
optional string field_2 = 2;
}
fun proto2ToProto3() {
val proto2Message = Proto2Format.Builder().field_1(null).field_2(null).build()
val proto3Message = Proto3Format.ADAPTER.decode(Proto2Format.ADAPTER.encode(proto2Message))
assertThat(proto3Message.field_1).isEqualTo("") // Default is used because value was not serialised
assertThat(proto3Message.field_2).isNull
}
fun proto3ToProto2() {
val proto3Message = Proto3Format.Builder().field_1("").field_2(null).build()
val proto2Message = Proto2Format.ADAPTER.decode(Proto3Format.ADAPTER.encode(proto3Message))
assertThat(proto2Message.field_1).isNull // Value was not serialised because it was the default
assertThat(proto2Message.field_2).isNull
}
fun proto3() {
val proto3Message = Proto3Format.Builder().field_1(null).field_2(null).build()
assertThat(proto3Message.field_1).isEqualTo("") // Default is used
assertThat(proto3Message.field_2).isNull
}
Currently, if we fail to supply a value for singular fields, we encounter exceptions like the following:
java.lang.NullPointerException: Parameter specified as non-null is null: method com.my.namespace.MyWireClass.<init>, parameter my_singular_field
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
No source file or test is named in the issue. Start by reproducing the Kotlin examples with the supplied proto2 and proto3 definitions, then trace Wire's proto3 singular-field code generation and encoding behavior. Done means singular fields accept null in builders and use the protobuf default when absent, while optional fields remain nullable.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- kotlin
- Domain
- api
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100