-
-
Notifications
You must be signed in to change notification settings - Fork 165
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support customizing $type
tag with key
annotation
#579
Conversation
184f33f
to
e33e4c8
Compare
@mrdziuban I think the approach looks great.
In the current codebase, I suppose it doesn't matter, because the parent I think a reasonably first pass would be to just fail loudly if a Another alternative would be to make the
Could you describe what you think is un-ergonomic about the current approach? That would help me give a proper answer |
e33e4c8
to
d050f72
Compare
Good idea, updated to do so.
I wasn't sure if adding |
Re: binary compatibility, I've made progress on it but am still having trouble with 5 problems:
I can fix the first two by implementing the upickle/upickle/core/src/upickle/core/Types.scala Lines 287 to 288 in d050f72
I'm stumped on the others. Do you have any idea how to handle them? |
The
|
d050f72
to
a3e24b5
Compare
Thanks for the tips, all the changes are binary compatible now 🎉 I'll hopefully be able to add some tests over the next couple of days |
a3e24b5
to
7762ef4
Compare
7762ef4
to
a66ecef
Compare
Added a couple tests, I think this is ready for review now |
@@ -55,7 +55,7 @@ object ADTs { | |||
object Hierarchy { | |||
sealed trait A | |||
object A{ | |||
implicit def rw: upickle.default.ReadWriter[A] = RW.merge(B.rw, C.rw) | |||
implicit def rw: upickle.default.ReadWriter[A] = RW.merge(core.Annotator.defaultTagKey, B.rw, C.rw) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For backwards compatibility, could we we leave the existing method un-deprecated?
I think it's reasonable to leave the existing functionality with the default in place rather than forcing people to explicitly pass in a defaultTagKey
every time they call merge
, and because of the use of varargs we can't give defaultTagKey
a default value. So having both methods available (with and without passing in the defaultTagKey
explicitly) seems like the way to go. Whether they have the same name or different names is fine either way for me
That would let all our tests remain unchanged, which is probably what we want since it ensures the user-facing API (as far as is tested) to remain stable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Definitely, updated
Left one code comment. One more request, could you update the documentation site to include the new functionality? You can use |
Also, could you update the PR description? A few lines summarizing what code changes are necessary, any alternatives you considered, and any other concerns you thought about, should be enough |
👍 done
For sure, updated to add these details |
Looks good to me. I kicked off CI and will merge it when green. Send me your bank details via email to [email protected] and i will close out the bounty |
Whoops sorry about the test failures, fixing in a minute |
8e1f084
to
b8fc81f
Compare
Thanks! |
This functionaly was removed in #579 when we made it configurable via `@key`, but it's easy enough to support both config mechanisms with `@key` taking precedence but `def tagName` being used as a fallback
Follow up to #579 The `Reader.merge` and `ReadWriter.merge` methods that don't take a `tagKey` param were retained for binary compatibility and updated to pass `Annotator.defaultTagKey` to the corresponding variant that does take a `tagKey`. This updates them to instead respect `Config#tagName`, which defaults to `Annotator.defaultTagKey` but may be overridden by downstream users. I also re-enabled mima checks and updated `mimaPreviousVersions` to just be `4.0.0`, but I'm happy to back out those changes if they're not desirable.
Closes #578
Adds support for customizing the key used a discriminator for sealed hierarchies. The default is still
$type
, but can be customized by annotating thesealed trait
with@key("customKey")
.The code changes necessary to support this in
Writer
were:tagKey
parameter toTaggedWriter.Leaf
TaggedWriter#findWriterWithKey
method that includes thetagKey
in its return valueTaggedWriter#write0
to callfindWriterWithKey
and pass thetagKey
through totaggedWrite
AttributeTagged#taggedWrite
to use the giventagKey
in place of the old default keyThe code changes necessary to support this in
Reader
were:tagKey
method toTaggedReader
, which defaults to the old default keytagKey
parameter toTaggedReader.Leaf
,TaggedReader.Node
,TaggedReadWriter.Leaf
, andTaggedReadWriter.Node
to override the default value inTaggedReader
AttributeTagged#taggedObjectContext
to use the givenTaggedReader
'stagKey
in place of the old default keyI tried instead to pass the
tagKey
through tofindReader
, butfindReader
is called in a number of contexts where it wasn't possible to get thetagKey
value, for example inTaggedReader#visitString
and thevisitValue
method within theObjVisitor
returned byAttributeTagged#taggedObjectContext
.The one limitation of the customization is when a member of a sealed hierarchy inherits from multiple parents that would result in different discriminators, e.g. if two parents have
@key
annotations with different arguments, or if one parent has a@key
annotation and another doesn't. In these cases, the macros will fail with an error telling the user what went wrong and suggesting ways to fix it: