I am trying to make a class that uses the Jackson to deserialize POJO's.
It looks like this...
public class DeserialiserImp<T> implements Deserialiser<T> {
protected ObjectMapper objectMapper = new ObjectMapper();
@Override
public T get(String content, Class clazz) throws IOException {
return (T) objectMapper.readValue(content, clazz);
}
@Override
public List<T> getList(String content, Class clazz) throws IOException {
return objectMapper.readValue(content, TypeFactory.collectionType(ArrayList.class, clazz));
}
}
I have 2 questions about this implementation.
The first is that I am passing the class type into the methods so the objectmapper knows the type that should deserialize. Is there a better way using generics?
Also in the get method I am casting an object returned from the objectMapper to T. This seems particularly nasty way of doing it as I have to cast T here and then I have to also cast the object type from the method which is calling it.
I am using Roboguice in this project so it would be nice if I could change the type through injection and then annotate the object which the Generic type I need it to return. I read about TypeLiteral and wondering if it could solve this problem?
The first is that I am passing the class type into the methods so the
objectmapper knows the type that should deserialize. Is there a better
way using generics?
Unfortunately not, and this is because of type erasure.
Also in the get method I am casting an object returned from the
objectMapper to T. This seems particularly nasty way of doing it as I
have to cast T here and then I have to also cast the object type from
the method which is calling it.
Do this instead :
@Override
public T get(String content, Class<T> clazz) throws IOException {
return objectMapper.readValue(content, clazz);
}
I am using Roboguice in this project so it would be nice if I could
change the type through injection and then annotate the object which
the Generic type I need it to return. I read about TypeLiteral and
wondering if it could solve this problem?
I don't really understand what you want to achieve, but since you need to pass the class anyways, is that still possible ?
So I think I figured it out in the end. Please comment if you see something wrong with what I am doing.
The interface is defined like so...
public interface Deserialiser<T> {
T get(String content) throws IOException;
List<T> getList(String content) throws IOException;
}
The implementation of the interface is like this...
public class DeserialiserImp<T> implements Deserialiser<T> {
private ObjectMapper objectMapper = new ObjectMapper();
private final Class<T> klass;
@Inject
public DeserialiserImp(TypeLiteral<T> type){
this.klass = (Class<T>) type.getRawType();
}
@Override
public T get(String content) throws IOException {
return objectMapper.readValue(content, klass);
}
@Override
public List<T> getList(String content) throws IOException {
return objectMapper.readValue(content, TypeFactory.collectionType(ArrayList.class, klass));
}
}
I bind the 2 like so..
bind(new TypeLiteral<Deserialiser<User>>(){}).annotatedWith(Names.named("user")).to(new TypeLiteral<DeserialiserImp<User>>(){});
Then all I need to do to use it is this...
@Inject
@Named("user")
private Deserialiser<User> deserialiserImp;
public void test(String userString) {
User user = deserialiserImp.get(UserString);
}
This pattern could also work well if the class as an abstract class to use in a DAO object
This article helped me