gwt-jackson
gwt-jackson copied to clipboard
Question: How can I get access to specific serializers/deserializers in a custom one
I'm trying to implement a custom serializer/deserializer for a project specific object type that uses a generic parameter.
we have a class FilterCriteria<V> Defined like this:
class FilterCriteria<V> { String key; FilterOperation operation; List<V> parameters; }
Right now the V generic parameter causes gwt-jackson to start building serializers for all Object types, and for Deserialisation I need to declare a whitelist so that the deserializer can work.
The key attribute actually is a name for a type that defines what the V generic parameter will be. So I would like to somehow use this to make a smarter deserializer.
In pure Java with Jackson we can use introspection, so we can make the serializer/deserializer smart. We have a mapping between key and the actual expected types for V. Users of the API need to subclass a specific FilterKey class that will build up a registry of supported types. Using this we can use introspection to decide what the actual type for V will be and as such we can serialize and deserialize properly.
But with gwt-jackson we can't use introspection so my idea was to use an annotation processor. The annotation processor would generate a custom serializer/deserializer for this type. At generation time it would lookup all subtypes of IFilterKey to determine what serializers/deserializers it needs.
However ... question is now ... how can I do that in a gwt-jackson. My assumption is that I can first read the name of the IFilterKey and based on that find back the expected type for V. But how can I instantiate a Deserializer for this type ? Can I just create/generate a static method to create an instance of the CriteriaFilterDeserializer with a large list of parameters which contain the deserializers for the detected V types ?
All the V
are a subtype of IFilterKey ?
Can you change FilterCriteria<V>
to FilterCriteria<V extends IFilterKey>
?
No IFilterKey has a generic parameter V. The IFilterKey is actually used in an API to make the filter parameters type safe (using a query builder API).
That is why I would like to lookup all subtypes of IFilterKey because they fill in this parameter V and based on that I have a limited list of types for V. The key in the JSON payload I can use to find back the IFilterKey subtype and with generics I can determine the actual type of the generic parameter, That is what we do in the Jackson serializer in Java.
Creating the custom deserializer should not be too hard. If you use an annotation processor or a gwt generator, you can easily build a map with the key being the type and the value, an instance of JsonDeserializer (or a class that lazily creates one).
To get a JsonDeserializer<MyType>, you can create an ObjectReader<MyType>, cast it to AbstractObjectReader and call getDeserializer : https://github.com/nmorel/gwt-jackson/blob/master/gwt-jackson/src/main/java/com/github/nmorel/gwtjackson/client/AbstractObjectMapper.java#L88 It's ugly but it's the only way to get an instance of JsonDeserializer currently.
The problem is to tell gwt-jackson to use the custom deserializer for FilterCriteria. Since it has a generic parameter, it will look for a static method or a constructor taking as argument a JsonDeserializer<V> and will create the deserializer for Object.
I don't have any workaround for that and it might be hard to change in the code.
Without a workaround it would make no sense for me to even try. Would it not be possible somehow to add a new gwt-jackson annotation to FilterCriteria to indicate that we want to fine-tune the list of allowed types for V ? Maybe allow a reference to a class that will be used at compile time to find the types from the compilation classpath ?
Right now gwt-jackson just picks up the V generic parameter and tries to find all types that extend or implement V.
I can guide you if want to try implementing it.
To instantiate a class, you can look at the code I use for the configuration class here :
https://github.com/nmorel/gwt-jackson/blob/master/gwt-jackson/src/main/java/com/github/nmorel/gwtjackson/rebind/RebindConfiguration.java#L258
And to use your type instead of the generic parameter V, the first method to look I think is : https://github.com/nmorel/gwt-jackson/blob/master/gwt-jackson/src/main/java/com/github/nmorel/gwtjackson/rebind/AbstractCreator.java#L718