Is it possible to get a hold of a TYPE_USE annotation from inside a custom deserializer?

85 views
Skip to first unread message

Bojan Tomic

unread,
Dec 27, 2017, 5:34:37 AM12/27/17
to jackson-user
I have a rather exotic use-case that I have to support. Types annotated with @Id need custom deserialization logic, e.g. the value should be Base64 decoded before deserializing it (not the only case).

This means a type such as List<@Id Key> will be represented as a list of Base64 Strings that I deserialize using my custom logic.

I originally have an AnnotatedType that I convert to JavaType using TypeFactory.constructType(annotatedType.getType()) prior to deserialization, which of course looses all the annotations.
Later, in my custom Deserializers instance, in its various findXXXDeserializer methods, I have no way to find the correct deserializer as the annotations needed for the decision are gone...

I was hoping the JDK8 module would have it's own TypeFactory-like mechanism to construct JavaType subclasses that preserve the annotations from AnnotatedTypes (e.g. AnnotatedTypeFactory.constructType(annotatedType)), but it doesn't seem to be the case.

Is there any way at all to implement what I'm after?

Bojan Tomic

unread,
Dec 27, 2017, 12:33:46 PM12/27/17
to jackson-user
Just for the sake of experimentation, I've cobbled together the following wrapper class:



class AnnotatedJavaType extends JavaType implements AnnotatedElement {

 
private final JavaType base;
 
private final Annotation[] annotations;

 
AnnotatedJavaType(JavaType base, Annotation[] annotations) { ... }

 
//all methods simply delegate to this.base
}



And the corresponding TypeFactory wrapper:

class AnnotatedTypeFactory {
   
 
JavaType construct(AnnotatedType type, TypeFactory typeFactory) {
   
if (type instanceof AnnotatedParameterizedType) {
     
JavaType[] args = Arrays.stream(((AnnotatedParameterizedType) type).getAnnotatedActualTypeArguments())
       
.map(arg -> fromJavaType(arg, typeFactory))
       
.toArray(JavaType[]::new);
 
     
TypeBindings bindings = TypeBindings.create(ClassUtils.getRawType(type.getType()), args);
   
     
return new AnnotatedJavaType(typeFactory.constructType(type.getType(), bindings), type.getAnnotations());
   
}
   
   
//handle wildcards, arrays, variables in the similar fashion

   
return new AnnotatedJavaType(typeFactory.constructType(type.getType()), type.getAnnotations());
 
}
}

Amusingly enough, it works! I'd never keep it in my code base, but it was an interesting experiment.

If the functionality I'm after is impossible (and I really hope it is not), would you be open to a contribution? I'd of course need some consultation/guidance on the approach, but would be happy to develop it.

Tatu Saloranta

unread,
Dec 28, 2017, 12:38:53 AM12/28/17
to jackson-user
I think this style of annotation is new (in Java 8?), and as such
there is no direct support for it at all.
Annotations are preserved for accessors themselves (fields, methods,
creator parameters), but not
for types. There is nothing to preserve that; JavaType only contains
resolved nested/generic types
and is not aware of possible annotations. Support could be added in
Jackson 3.0, although things
could get quite complicated pretty soon.

You probably access annotations in question via specific
`AnnotatedMember` of `BeanProperty`
(from within `createContextual`), but I have never used these types of
annotations.
So I think you'll be trailblazing here.

-+ Tatu +-

>
> --
> You received this message because you are subscribed to the Google Groups
> "jackson-user" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to jackson-user...@googlegroups.com.
> To post to this group, send email to jackso...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Tatu Saloranta

unread,
Dec 28, 2017, 12:42:28 AM12/28/17
to jackson-user
As per my other note, this would need to be in Jackson 3.0 I think,
due to multiple reasons.

I am bit hesitant to say much more since I really fear all complexity
that would come from trying
to create parallel annotation processing system. I can see some
benefits from type annotations,
but it wouldn't come for free, if we are talking about whole
AnnotationIntrospector style system.

However: if the idea would be to do something simpler -- I don't
really see need for full AnnotationIntrospector
in this case, to be honest -- for example, simply keep track of
annotations for type, offer access... well,
that seems quite doable and useful. If so, `JavaType` could just have
`findAnnotation(Class<?> type)` method
or something?

-+ Tatu +-



>
>
>
>
> On Wednesday, December 27, 2017 at 11:34:37 AM UTC+1, Bojan Tomic wrote:
>>
>> I have a rather exotic use-case that I have to support. Types annotated
>> with @Id need custom deserialization logic, e.g. the value should be Base64
>> decoded before deserializing it (not the only case).
>>
>> This means a type such as List<@Id Key> will be represented as a list of
>> Base64 Strings that I deserialize using my custom logic.
>>
>> I originally have an AnnotatedType that I convert to JavaType using
>> TypeFactory.constructType(annotatedType.getType()) prior to deserialization,
>> which of course looses all the annotations.
>> Later, in my custom Deserializers instance, in its various
>> findXXXDeserializer methods, I have no way to find the correct deserializer
>> as the annotations needed for the decision are gone...
>>
>> I was hoping the JDK8 module would have it's own TypeFactory-like
>> mechanism to construct JavaType subclasses that preserve the annotations
>> from AnnotatedTypes (e.g.
>> AnnotatedTypeFactory.constructType(annotatedType)), but it doesn't seem to
>> be the case.
>>
>> Is there any way at all to implement what I'm after?
>

Bojan Tomic

unread,
Dec 28, 2017, 5:16:59 AM12/28/17
to jackson-user
Yes, TYPE_USE annotations and AnnotatedType were added in Java 8.
As you noted, processing these can get quite hairy, but at least some support in Jackson would be very welcome.
I am intimately familiar with the complexities involved, as I am the developer behind GeAnTyRef, a fork of GeTyRef (a library similar to ClassMate), that deeply supports working with AnnotatedTypes.
I'm of the opinion Jackson would greatly gain in versatility if this style of annotations was supported (as it makes it possible to convey (de)serialization hints on a very granular level).
As I've mentioned, I'd be happy to contribute in order to get this feature faster, if you'd be interested.

Tatu Saloranta

unread,
Dec 28, 2017, 4:08:49 PM12/28/17
to jackson-user
On Thu, Dec 28, 2017 at 2:16 AM, Bojan Tomic <veg...@gmail.com> wrote:
> Yes, TYPE_USE annotations and AnnotatedType were added in Java 8.
> As you noted, processing these can get quite hairy, but at least some
> support in Jackson would be very welcome.
> I am intimately familiar with the complexities involved, as I am the
> developer behind GeAnTyRef, a fork of GeTyRef (a library similar to
> ClassMate), that deeply supports working with AnnotatedTypes.

Ah. Yes, your help here is appreciated and we could use your expertise.
Especially since you have an actual use case -- it's much easier to
add support for existing
use case, as opposed to expected or potential one.

> I'm of the opinion Jackson would greatly gain in versatility if this style
> of annotations was supported (as it makes it possible to convey
> (de)serialization hints on a very granular level).
> As I've mentioned, I'd be happy to contribute in order to get this feature
> faster, if you'd be interested.

Yes, I think that would make sense.

As I said, `master` branch would be the the way to go at this point.
Code has been refactored quite a bit
since 2.9 in some places, but not so much wrt functionality for this,
I think. But code for 3.0 requires Java 8,
and 2 out of 3 modules (parameter names, Optional and other new types)
are part of `jackson-databind` now.

-+ Tatu +-

遗迹

unread,
Oct 31, 2021, 12:56:27 PM10/31/21
to jackson-user
Are there any solution for this? In my case, I use it for OAS discriminator annotation. It looks like:

```kotlin
class Pet(val pet: Discriminator("petType") OneOf2<Dog, Cat>)
```

Without TYPE_USE annotation support, I can't get the discriminator information. 
Or are there any better choice to storage the information?

Thank you.

Tatu Saloranta

unread,
Nov 1, 2021, 1:00:12 PM11/1/21
to jackson-user
On Sun, Oct 31, 2021 at 9:56 AM 遗迹 <canpo...@gmail.com> wrote:
Are there any solution for this? In my case, I use it for OAS discriminator annotation. It looks like:

That thread is from 2017. Please start a new one with your question...

-+ Tatu +-
 

veg...@gmail.com

unread,
Nov 3, 2021, 2:09:24 PM11/3/21
to jackson-user
In all fairness, I don't think the situation has changed at all regarding this, so the info and the question is still fresh :)

Tatu Saloranta

unread,
Nov 3, 2021, 9:03:26 PM11/3/21
to jackson-user
That may well be, but I think it's better to summarize the situation and drop the longer discussions when there's been a long pause.

-+ Tatu +-

Reply all
Reply to author
Forward
0 new messages