-
Notifications
You must be signed in to change notification settings - Fork 594
Description
Hi Wire team 👋,
First of all, thanks for Wire — it’s a fantastic tool and we’re happily using it in production with Kotlin and gRPC. I really like the wire function that compiling the optional fields to nullable properties.
While integrating Wire into a multi-language environment, we ran into a few Kotlin codegen limitations that I believe could be valuable feature additions. I’d like to propose the following enhancements:
1. Automatic field name conversion to lowerCamelCase in Kotlin
Problem
Our .proto files are shared across multiple languages (Go, Python, JS, Kotlin, etc.), so we use snake_case field names in proto files for consistency.
Example:
message FeatureReq {
string feature_name = 1;
int64 created_at = 2;
}Currently, Wire generates Kotlin properties exactly as-is:
val feature_name: String
val created_at: LongHowever, idiomatic Kotlin strongly prefers lowerCamelCase:
val featureName: String
val createdAt: LongRequest
Provide an option in Kotlin codegen to automatically convert proto field names to lowerCamelCase, while still mapping correctly to the original proto names.
Possible approaches: A codegen flag (e.g. kotlin { camelCaseFields = true }). Or default behavior aligned with Kotlin conventions (similar to how some JSON serializers behave)
2. Additional constructor with required (non-optional) fields only
Problem
Wire-generated Kotlin message classes typically expose a single constructor where all fields (including optional ones) are nullable or defaulted.
For example:
FeatureReq(
featureName = featureName,
createdAt = createdAt,
description = null
)This makes it easy to accidentally construct invalid domain objects and weakens compile-time guarantees.
Request
If there are some optional fields, generate an additional constructor where:
-
Non-optional fields are required parameters
-
Optional fields are omitted or defaulted
Example:
// existing constructor
FeatureReq(
featureName: String = "",
createdAt: Long = 0L,
description: String? = null
)
// new constructor
constructor(
featureName: String,
createdAt: Long,
description: String? = null
)This would significantly improve Kotlin ergonomics and domain safety.
3. fieldOrFail accessors for optional fields
Problem
Optional fields are nullable in Kotlin, which is correct at the model level, but in some layers (e.g. application logic) a missing value should be treated as a programmer error.
Currently, users must manually write:
val value = featureReq.description
?: error("description is required")Request
For optional fields, generate an additional accessor:
val descriptionOrFail: StringWhich throws a clear exception if the field is null.
This pattern is very common in Kotlin codebases and would greatly reduce boilerplate while making intent explicit.