-
Notifications
You must be signed in to change notification settings - Fork 174
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
Annotation given to constructor parameters containing value class
as argument does not work
#651
Comments
As I commented in the issue above (#748 ), it appears that this happens to all other properties in the constructor as well. I made a small reproduction here |
@cowtowncoder In the sample code below, I want to do something like copying annotations from the lower constructor to the upper constructor. // Excerpts from the decompile results
public final class Data {
private Data(int ui) {
this.ui = ui;
}
// $FF: synthetic method
public Data(@JsonProperty("prop") int ui, DefaultConstructorMarker $constructor_marker) {
this(ui);
}
} This is because the bytecode generated by I have prototyped the following code using The main point is that I try to reproduce the On the other hand, I have the following concerns about this implementation.
Do you have a better idea on how to implement this, or even how to solve this problem? |
@k163377 yes, I can see challenges there. But one clarifying question: is the need for copying annotations across Constructors within same class? (I think so, just confirming). I guess in some way this would seem to indicate need for some kind of handler which would be given a set of constructors, with annotations, but allowing modifying that set of annotations. This would occur for single classes at a time, during basic annotation introspection -- so within Actually I guess handler should be able to post-process any |
Yes, that is correct (if
Does this mean adding functionality to |
No, like I said above it'd be for
|
@cowtowncoder
Personally, I feel that the operations being performed here could be interpreted as processing for individual |
@k163377 The idea would be to add handler used by
|
I feel there are some misunderstandings, so let me confirm a couple of things. It is not possible to get an instance of Are you talking about introducing a Personally, I feel that the safest approach is to add the following interface to public class AI extends NopAnnotationIntrospector {
public void modifyIntrospected(AnnotatedMember m) {
if (m instanceof AnnotatedConstructor) {
AnnotatedConstructor ac = (AnnotatedConstructor) m;
for (int i = 0; i < ac.getParameterCount(); i++) {
AnnotationMap am = ac.getParameterAnnotations(i);
am.add(...);
}
} else if (m instanceof AnnotatedParameter) {
AnnotatedParameter ap = (AnnotatedParameter) m;
AnnotationMap am = ap.getAllAnnotations();
am.add(...);
}
}
} |
Yes. That is why I said the we need a new handler called by ClassIntrospector (or passed to it, to use). |
Thank you. I do not understand how this will be implemented, but I am relieved to know that at least the concerns I mentioned have been taken into consideration. |
@k163377 Fair. I do not know exactly how, either, but I know that the place where action would make most sense -- regardless of how it can be customized -- is I am definitely open to suggestion on how to allow customization, and how configuration gets piped through. But this is the place where I feel it should happen, and if we can make it so, would work very well: implementation of whatever modifier is provided could be quite simple. |
Here's another example that does not work, from
@JvmInline
value class MyId(val id: UUID = UUID.randomUUID())
sealed interface SealedType
enum class TypeA : SealedType {
FOO
}
data class FooDto (
val myId: MyId = MyId(),
@JsonDeserialize(using = SealedTypeDeserializer::class)
val type: SealedType = TypeA.FOO,
)
fun main() {
val om = ObjectMapper().registerKotlinModule()
val json = om.writeValueAsString(FooDto())
println(json)
val obj = om.readValue<FooDto>(json)
println(obj)
}
val types: Map<String, SealedType> = listOf(TypeA.entries).flatten().associateBy { it.name }
class SealedTypeDeserializer : JsonDeserializer<SealedType>() {
override fun deserialize(p: JsonParser, ctxt: DeserializationContext): SealedType {
return types[p.text] ?: error("Finner ikke mapping for ${p.text}")
}
} |
Currently, annotations given to constructor parameters containing
value class
as an argument are ignored.The cause is that annotations are only given to parameters of the synthetic constructor (ignored by
Jackson
).About workaround
Please change to give annotations to
getter
,field
, etc.About fix
An experimental project,
jackson-module-kogera
, fixed this problem by introducing the followinghttps://github.com/ProjectMapK/jackson-module-kogera/blob/develop/src/main/kotlin/io/github/projectmapk/jackson/module/kogera/KotlinClassIntrospector.kt
Please note that this code appears to be unreviewed and fragile.
Also, currently
jackson-module-kotlin
does not support deserialization ofvalue class
(#650).The text was updated successfully, but these errors were encountered: