Skip to content

Add preservingProtoFieldNames option#3521

Merged
oldergod merged 2 commits intosquare:masterfrom
jdbp-classpass:jp/json
Feb 27, 2026
Merged

Add preservingProtoFieldNames option#3521
oldergod merged 2 commits intosquare:masterfrom
jdbp-classpass:jp/json

Conversation

@jdbp-classpass
Copy link
Contributor

As discussed on #2452, the upstream Google protobuf libraries (e.g. JsonFormat) can be configured to serialize with the unmodified field names from the proto files. Wire also supports this capability in Swift (

public enum KeyNameEncodingStrategy {
// Convert key names to `camelCase`
case camelCase
// Maintain the original field names, typically `snake_case`
case fieldName
}
) but not in Java.

Adding a preservingProtoFieldNames option to WireJsonAdapterFactory (Moshi) and WireTypeAdapterFactory (Gson) allows Wire's JSON implementation to be configured for field name preservation as well.

As discussed on square#2452, the upstream Google protobuf
libraries (e.g. `JsonFormat`) can be configured to serialize with the unmodified field names from
the proto files. Wire also supports this capability in Swift
(https://github.com/square/wire/blob/ca1e09e297f96c52b4615f75e95780be0b10eeb7/wire-runtime-swift/src/main/swift/Codable/CodingUserInfoKey%2BWire.swift#L48-L53)
but not in Java.

Adding a `preservingProtoFieldNames` option to `WireJsonAdapterFactory` (Moshi) and `WireTypeAdapterFactory`
(Gson) allows Wire's JSON implementation to be configured for field name preservation as well.
@jdbp-classpass
Copy link
Contributor Author

@oldergod the tests are failing because adding the second boolean parameter is an ABI break. I can modify wire-gson-support/api/wire-gson-support.api etc to make the build pass but there is a risk if code compiled against the older version is linked against the newer version. What do you think the right thing to do here is?

Copy link
Member

@oldergod oldergod left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's dump the api ./gradlew apiDump and push. I think it's fine since we have the jmvoverloads

)
}

private val ALL_TYPES_PROTO2_JSON get() = loadJson("all_types_proto2.json")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you put them all back in the companion object?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They need to be outside the companion object because loadJson now depends on the value of jsonLibrary.preservingProtoFieldNames, and jsonLibrary is a lateinit var (which is also why there's a get() on the val)

@oldergod
Copy link
Member

Very sweet. Thank you

@oldergod oldergod merged commit 40b9da0 into square:master Feb 27, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants