Separate a nested implementation with a dot, not a dollar - #4
Merged
Merged
Conversation
Following jackson-module-scala#839. An implementation nested in a class
other than the root was written {"@type":"Boxed$Same"}; it is now
{"@type":"Boxed.Same"}, which is how jackson-databind separates a name
from what encloses it. The JVM writes that boundary as a $, so the two
spellings differ and this is a change to the JSON.
Only a real nesting boundary becomes a dot. A $ is a legal character in
a Java identifier, so a class can carry one in a name of its own making,
and the enclosing class chain is what tells the two apart - a class with
a $ in its own name has no enclosing class at that position. This is the
counterpart of the Scala module's concern with `::` compiling to
$colon$colon, and there is now a fixture named Odd$Name that asserts such
a name survives intact.
The Scala module has to convert the dot back to a $ before looking a name
up, since it resolves by rebuilding class names and calling Class.forName.
Nothing of the sort is needed here: names are resolved against the
hierarchy's own table, built from the PermittedSubclasses attribute, so
the derived name is simply the key. A dot in a @type still cannot address
a package.
93 tests.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012hxYY9KPDAMXADWzjBHNV4
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.
Following jackson-module-scala#839.
An implementation nested in a class other than the root was written
{"@type":"Boxed$Same"}. It is now{"@type":"Boxed.Same"}— the way jackson-databind separates a name from what encloses it. This changes the JSON, so it is a wire-format change, not a refactor.Only real nesting becomes a dot
A
$is a legal character in a Java identifier, so a class can carry one in a name of its own making. The enclosing-class chain is what tells the two apart: a class with a$in its own name has no enclosing class at that position, so that$is left alone.This is the counterpart of the Scala module's concern with
::compiling to$colon$colon. There is a fixture namedOdd$Nameasserting such a name survives intact:{"expr":{"@type":"Odd$Name","head":1,"tail":2}} {"expr":{"@type":"Grouped.Inner","v":5}}Simpler here than in Scala
The Scala module has to convert the dot back to a
$before looking a name up, because it resolves by rebuilding candidate class names and callingClass.forName. Nothing of the sort is needed here — names are resolved against the hierarchy's own table, built from thePermittedSubclassesattribute, so the derived name is simply the map key. A dot in a@typestill cannot address a package, and is still never handed toClass.forName.So this PR changes
typeNameForand nothing else in the main sources.Tests
93 total. Three existing name-shape assertions updated (
SealedPolymorphismTest,SealedTypesTest,MixInTest), plus three new ones: the dot for an enclosing class, a$that is part of the class name surviving, andtypeNameForcovering both directly.🤖 Generated with Claude Code
https://claude.ai/code/session_012hxYY9KPDAMXADWzjBHNV4