Skip to content
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

Jackson2JsonRedisSerializer should allow to customise the JavaType for deserialization via getJavaType() [DATAREDIS-354] #930

Closed
spring-projects-issues opened this issue Nov 12, 2014 · 4 comments
Assignees

Comments

@spring-projects-issues
Copy link

@spring-projects-issues spring-projects-issues commented Nov 12, 2014

Benjamin Brodie opened DATAREDIS-354 and commented

The Jackson2JsonRedisSerializer has an overridable getJavaType(Class<?> class) method, but it does not delegate to this method to determine the javaType used by the object mapper when deserializing.

The fix is simple. Instead of setting the private field JavaType javaType to the Class<T> type passed in from the constructor, it should be set to the type returned by getJavaType(Class<?> class)


Affects: 1.4.1 (Evans SR1)

Referenced from: pull request #113

Backported to: 1.4.2 (Evans SR2)

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Nov 12, 2014

Benjamin Brodie commented

This fix is to change the constructor from:

public Jackson2JsonRedisSerializer(Class<T> type) {
     this.javaType = TypeFactory.defaultInstance().constructType(type);
}

to:

 public Jackson2JsonRedisSerializer(Class<T> type) {
     this.javaType = getJavaType(type);
}

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Nov 13, 2014

Thomas Darimont commented

Hello Benjamin,

I applied your suggested change to Jackson2JsonRedisSerializer and JacksonJsonRedisSerializer as well. Additionally I introduced a constructor that takes a JavaType instead of a Class<T>.

Do you have an example at hand where you need to customize the JavaType via an overridden getJavaType(...)?

Cheers,
Thomas

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Nov 13, 2014

Benjamin Brodie commented

This case is necessary when you are using generics, or else Jackson can't deserialize back into the target object correctly, as it does not know the generic type.

Here is a simple example:

Say you have a Message<T> object which looks like this:

public class Message<T> {
  String name;
  T data;
}

Then you expose a redis template:

RedisTemplate<String, Message<MyData>> redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Message.class));

Jackson does not know the generic type is MyData. This can be tested by using a ListOperations<String, Message<MyData>> pushing on a Message object and then poping it off... the MyData data field will not be deserialized as expected, using a debugger you can see that the field is actually a LinkedHashMap type.

According to the JavaDoc on the getJavaType method, you should be able to override like this:

@Override
protected JavaType getJavaType(Class<?> clazz) {
  if (Message.class.isAssignableFrom(clazz)) {
    return TypeFactory.defaultInstance().constructParametricType(Message.class, MyData.class);
  } else {
    return TypeFactory.defaultInstance().constructType(clazz);
  {
}

But since the class never actually calls that method, it doesn't accomplish anything.

Passing in a JavaType in the constructor may be an even better solution, as this does not require a subclass to accomplish.

@spring-projects-issues
Copy link
Author

@spring-projects-issues spring-projects-issues commented Nov 26, 2014

Thomas Darimont commented

Please revise

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants