Use the runtime type for a wildcard element type - #3112
Open
HuzaifaChaudary wants to merge 1 commit into
Open
Conversation
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
Author
|
@googlebot I signed it! |
a field like List<? extends Base> holding a Sub lost the fields that Sub adds , because getRuntimeTypeIfMoreSpecific only looked at the runtime type for a Class or a type variable , and ? extends Base is neither . so List<? extends Base> and List<Base> gave different json for the same value . a wildcard says nothing more than its upper bound , so this reads the bound and then decides the same way as before . when the bound is a parameterized type the declared type is kept , same as gson already does for a plain parameterized type , because the runtime class would drop the type arguments . closes google#1870
HuzaifaChaudary
force-pushed
the
wildcard-runtime-type
branch
from
September 5, 2026 19:55
1b2b61a to
5843050
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1870
getRuntimeTypeIfMoreSpecificonly looks at the runtime type for aClassor aTypeVariable.? extends Baseis aWildcardType, so it is neither , and the adapter forthe declared bound is used instead :
same value , same field , different json .
a wildcard says nothing more than its upper bound , so this reads the bound and then decides
the same way it already does for a plain type . the bound is only used to make the decision ,
the declared type is still what gets kept when it is parameterized , so
? extends List<String>behaves like
List<String>and does not lose its type arguments . that is why this reads thebound rather than just adding
|| type instanceof WildcardType, which would swap in the rawruntime class and drop them .
while testing i found a worse case of the same cause that is not in the report .
List<? extends CharSequence>holding aStringand aStringBuilderserialized as[{},{}], because gson fell back to a reflective adapter for the interface . the strings weresimply gone .
List<CharSequence>gives["s","t"]. that is fixed by the same change .four tests added , covering a wildcard list , a wildcard map value , and a wildcard reached
through a type variable . the fourth goes the other way and pins that
Collection<? extends ParameterizedBase<String>>still keeps the declared type , so the changeis not too loose . it passes with and without .
4637 tests pass in the gson module , 0 failures , and the full reactor is 4856 across all eight
modules .
spotless:checkis clean .one related thing i deliberately left out .
registerTypeAdapter(Base.class, adapter)is stillignored when the element type is
? extends Base, because the lookup token never matches oneregistered for
Base.class. that needs the wildcard stripped at adapter lookup time , wherethere is already a
// TODO: strip wildcards?inGsonTypes, and it is a wider change toyour internals , so it seemed better to leave that call to you . this change still improves that
case , the subclass fields stop disappearing .